From: <Saved by Windows Internet Explorer 7>
Subject: Multicore Hardware and the Future of Ruby - O'Reilly Ruby
Date: Wed, 16 Jan 2008 20:09:56 +0100
MIME-Version: 1.0
Content-Type: multipart/related;
	type="text/html";
	boundary="----=_NextPart_000_0000_01C8587B.C3B54E40"
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3198

This is a multi-part message in MIME format.

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: text/html;
	charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_and_the_fut.html

=EF=BB=BF<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" =
"http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<HTML xmlns=3D"http://www.w3.org/1999/xhtml"><HEAD><TITLE>Multicore =
Hardware and the Future of Ruby - O'Reilly Ruby</TITLE>
<META http-equiv=3DContent-Type content=3D"text/html; charset=3Dutf-8">
<META content=3D"ruby, rails, multicore, thread, rubinious, jruby, dhh"=20
name=3Dkeywords>
<META=20
content=3D"Consider this fact: Multi-core CPUs are not only the future, =
they're the only way CPUs can continue to grow at their current pace. =
It's also a hotly debated subject in the software world. Multi-threaded =
programming is different and not seen..."=20
name=3Ddescription>
<META content=3D"Jun.  7, 2007" name=3Ddate>
<META content=3D"David Fayram" name=3Dauthor>
<META content=3D"Multicore Hardware and the Future of Ruby" =
name=3Dtitle>
<META content=3D"Multicore Hardware and the Future of Ruby" =
name=3Dpagename>
<META content=3D"O'Reilly Ruby" name=3Dsite>
<SCRIPT src=3D"http://www.oreillynet.com/engine.js" =
type=3Dtext/javascript></SCRIPT>

<SCRIPT src=3D"http://www.oreillynet.com/common.js" =
type=3Dtext/javascript></SCRIPT>

<SCRIPT src=3D"http://www.oreillynet.com/blogs/mt-site.js"=20
type=3Dtext/javascript></SCRIPT>

<SCRIPT src=3D"http://www.oreillynet.com/blogs/popup-media-player.js"=20
type=3Dtext/javascript></SCRIPT>
<LINK title=3DAtom href=3D"http://www.oreillynet.com/ruby/blog/atom.xml" =

type=3Dapplication/atom+xml rel=3Dalternate><LINK title=3D"RSS 2.0"=20
href=3D"http://www.oreillynet.com/ruby/blog/index.xml" =
type=3Dapplication/rss+xml=20
rel=3Dalternate><LINK href=3D"http://www.oreillynet.com/blogs/style.css" =

type=3Dtext/css rel=3Dstylesheet><LINK=20
href=3D"http://www.oreillynet.com/ruby/blog/style.css" type=3Dtext/css=20
rel=3Dstylesheet>
<META content=3D"MSHTML 6.00.6000.16587" name=3DGENERATOR></HEAD>
<BODY>
<DIV class=3Dnoindex id=3Dheader>
<H1><A href=3D"http://www.oreillynet.com/ruby/"><IMG alt=3D"O'Reilly =
Ruby"=20
src=3D"http://www.oreillynet.com/ruby/blog/images/logo.gif" =
border=3D0></A></H1>
<DIV id=3Dtabs>
<DIV id=3Daccount-links><A=20
href=3D"http://www.oreillynet.com/cs/user/login?x-redirect=3D/cs/user/hom=
e">Sign=20
In/My Account</A> | <A =
href=3D"http://epoch.oreilly.com/shop/cart.orm">View=20
Cart</A> </DIV>
<OL>
  <LI><A href=3D"http://www.oreillynet.com/"><IMG height=3D16 =
alt=3D"O'Reilly Network"=20
  src=3D"http://www.oreillynet.com/images/tabs/orn_black.gif" =
width=3D113></A> </LI>
  <LI><A href=3D"http://www.oreilly.com/"><IMG height=3D16 =
alt=3Doreilly.com=20
  src=3D"http://www.oreillynet.com/images/tabs/ora_gray.gif" =
width=3D82></A> </LI>
  <LI><A href=3D"http://safari.oreilly.com/"><IMG height=3D16 =
alt=3D"Safari Bookshelf"=20
  src=3D"http://www.oreillynet.com/images/tabs/safari_gray.gif" =
width=3D114></A>=20
  </LI>
  <LI><A href=3D"http://conferences.oreilly.com/"><IMG height=3D16 =
alt=3DConferences=20
  src=3D"http://www.oreillynet.com/images/tabs/conf_gray.gif" =
width=3D88></A>=20
</LI></OL></DIV><!-- end #tabs -->
<OL id=3Dmenubar>
  <LI><A href=3D"http://www.oreillynet.com/pub/q/articles">Articles</A> =
</LI>
  <LI><A href=3D"http://weblogs.oreillynet.com/">Weblogs</A> </LI>
  <LI><A href=3D"http://www.oreilly.com/catalog/">Books</A> </LI>
  <LI><A href=3D"http://learninglab.oreilly.com/">Courses</A> </LI>
  <LI><A href=3D"http://www.oreilly.com/store/series/sc.csp">Short =
Cuts</A> </LI>
  <LI><A href=3D"http://www.oreillynet.com/podcasts/">Podcasts</A> =
</LI></OL>
<DIV style=3D"CLEAR: both"></DIV>
<DIV id=3Dleaderboard><IMG style=3D"FLOAT: right" height=3D90 =
alt=3Dadvertisement=20
src=3D"http://www.oreillynet.com/images/ads/ad-tag-vertical.gif" =
width=3D11=20
border=3D0>=20
<DIV style=3D"MARGIN: 0px auto; WIDTH: 728px"><!-- begin ad tag  =
(tile=3D1) -->
<SCRIPT language=3DJavaScript type=3Dtext/javascript>=0A=
//<![CDATA[=0A=
var ord =3D (ord !=3D null ? ord : Math.random()*10000000000000000 );=0A=
document.write('<script language=3D"JavaScript" =
src=3D"http://ad.doubleclick.net/adj/ttm.ruby/weblog;tile=3D1;sz=3D728x90=
;ord=3D' + ord + '?" type=3D"text/javascript"><\/script>');=0A=
//]]>=0A=
</SCRIPT>
<NOSCRIPT><A=20
href=3D"http://ad.doubleclick.net/jump/ttm.ruby/weblog;tile=3D1;sz=3D728x=
90;ord=3D123456789?"=20
target=3D_blank><IMG height=3D90 alt=3D"" src=3D"" width=3D728 =
border=3D0></A> </NOSCRIPT><!-- End ad tag --></DIV></DIV><!--This =
defines the site name (featureBarSection) -->
<DIV class=3Dtinywhite>
<DIV id=3Dtextbar><!-- begin ad tag -->
<SCRIPT language=3DJavaScript type=3Dtext/javascript>=0A=
//<![CDATA[=0A=
var ord =3D (ord !=3D null ? ord : Math.random()*10000000000000000 );=0A=
document.write('<script language=3D"JavaScript" =
src=3D"http://ad.doubleclick.net/adj/ttm.ruby/textbar;sz=3D$widthx$height=
;tile=3D1;ord=3D' + ord + '?" type=3D"text/javascript"><\/script>');=0A=
//]]>=0A=
</SCRIPT>
<NOSCRIPT><A=20
href=3D"http://ad.doubleclick.net/jump/ttm.ruby/textbar;sz=3D$widthx$heig=
ht;tile=3D1;ord=3D123456789?"=20
target=3D_blank><IMG height=3D$height alt=3D"" src=3D"" width=3D$width=20
border=3D0></A></NOSCRIPT> <!-- End ad tag --></DIV></DIV></DIV><!-- end =
#header -->
<DIV id=3Dcontent>
<DIV id=3Dblog><!-- 3 Featurebar files define different ad zones --><!-- =
Featurebar1: XML, ONLamp, Sysadmin, Ruby, ONJava, eTel, Database --><!-- =
Featurebar2: Mac, Windows --><!-- Featurebar3: Linux --><!-- techtracker =
october update --><!--This defines the site name (featureBarSection) =
--><!-- This defines the ad zone -->
<DIV id=3Dfeaturebar align=3Dcenter><!-- begin ad tag -->
<SCRIPT language=3DJavaScript type=3Dtext/javascript>=0A=
//<![CDATA[=0A=
var ord =3D (ord !=3D null ? ord : Math.random()*10000000000000000 );=0A=
document.write('<script language=3D"JavaScript" =
src=3D"http://ad.doubleclick.net/adj/ttm.ruby/weblog;tn=3D3;tw=3D300;th=3D=
55;to=3Dh;tcs=3D0;tcp=3D0;ta=3Dcenter;tva=3Dbottom;tc=3Dffffff;tnm=3D3;te=
=3D1;sz=3D100x50;ord=3D' + ord + '?" =
type=3D"text/javascript"><\/script>');=0A=
//]]>=0A=
</SCRIPT>
<NOSCRIPT><A=20
href=3D"http://ad.doubleclick.net/adj/ttm.ruby/weblog;tn=3D3;tw=3D300;th=3D=
55;to=3Dh;tcs=3D0;tcp=3D0;ta=3Dcenter;tva=3Dbottom;tc=3Dffffff;tnm=3D3;te=
=3D1;sz=3D100x50;ord=3D123456789?"=20
target=3D_blank><IMG height=3D50 alt=3D"" src=3D"" width=3D100 =
border=3D0></A></NOSCRIPT> <!-- End ad tag --></DIV>
<DIV class=3Dpost id=3Dentry-20518>
<DIV class=3Dpost-header><!-- ISI_LISTEN_START --><SPAN =
class=3DISI_MESSAGE><!--  This weblog is brought to you by the O'Reilly =
Ruby  --></SPAN><!-- JJJ =0A=
 hmm -->
<H2 class=3Dpost-title><A class=3Dpermalink=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html">Multicore=20
Hardware and the Future of Ruby</A></H2><SPAN class=3DISI_IGNORE>
<UL class=3Dlisten><!-- JLW Davidm --><!-- <li class=3D"option"><a =
href=3D"http://asp2.readspeaker.net/cgi-bin/oreillyrsone?lang=3Dus&voice=3D=
Paul&customerid=3D171&url=3Dhttp://www.oreillynet.com/ruby/blog/">listen =
to all posts</a></li> -->
  <LI class=3Dbutton><A=20
  =
href=3D"http://asp2.readspeaker.net/cgi-bin/oreillyrsone?lang=3Dus&amp;vo=
ice=3DPaul&amp;customerid=3D171&amp;url=3Dhttp://www.oreillynet.com/ruby/=
blog/2007/06/multicore_hardware_and_the_fut.html"=20
  target=3D_new>listen <IMG height=3D9 alt=3D"Speech Icon"=20
  src=3D"http://www.oreillynet.com/images/icon_listen_small.gif" =
width=3D10></A>=20
  </LI></UL></SPAN>
<DIV class=3Dpost-byline>Thursday June 7, 2007 <SPAN=20
class=3DISI_IGNORE>7:59AM</SPAN><BR>by <A=20
href=3D"http://www.oreillynet.com/pub/au/2645">David Fayram</A><SPAN=20
class=3DISI_IGNORE> in <A=20
href=3D"http://www.oreillynet.com/ruby/blog/technical/">Technical</A></SP=
AN>=20
</DIV><!-- .byline --></DIV><!-- .post-header -->
<P><SPAN><!-- AddThis Bookmark Button BEGIN --><!--=0A=
<a href=3D"http://www.addthis.com/bookmark.php" onclick=3D"addthis_url   =
=3D location.href; addthis_title =3D document.title; return =
addthis_click(this);" target=3D"_blank"><img =
src=3D"http://s5.addthis.com/button1-bm.gif" width=3D"125" height=3D"16" =
border=3D"0" alt=3D"AddThis Social Bookmark Button" /></a> <script =
type=3D"text/javascript">var addthis_pub =3D =
'oreillynetwork';</script><script type=3D"text/javascript" =
src=3D"http://s5.addthis.com/js/widget.php?v=3D10"></script>  =0A=
--><!-- AddThis Bookmark Button END --></SPAN>
<P><!-- moving the location of the listen button higher ##### -->
<DIV class=3Dpost-content>
<P>Consider this fact: Multi-core CPUs are not only the future, =
they=E2=80=99re the only=20
way CPUs can continue to grow at their current pace. It=E2=80=99s also a =
hotly debated=20
subject in the software world. Multi-threaded programming is different =
and not=20
seen as often as procedural programming, and therefore it=E2=80=99s not =
yet as well=20
understood. So the question is, how can programming languages (and Ruby =
in=20
particular) make it easier to harness these systems?</P>
<P>As Ruby struggles to graduate from its current implementation into =
something=20
more powerful, we=E2=80=99ve already seen several projects attempt to =
update Ruby to=20
help developers cope. Those who=E2=80=99ve been working with Ruby for =
awhile may=20
remember <A href=3D"http://www.atdot.net/yarv/">YARV</A>, which promises =
to=20
provide more threading support. <A=20
href=3D"http://jruby.sourceforge.net/">JRuby</A> offers all the power of =
Java=E2=80=99s=20
threads to Ruby, if it can harness it. And Evan Phoenix=E2=80=99s small =
but rapidly=20
growing project <A href=3D"http://rubini.us/">Rubinius</A> is attempting =
to be the=20
next big contender. </P>
<P>No matter what implementation becomes the next de-facto Ruby =
platform, one=20
thing is clear: People are interested in taking advantage of their =
newer, more=20
powerful multi-core systems (as the recent surge in interest in Erlang =
in recent=20
RailsConf and RubyConfs has shown). As Ruby becomes increasingly part of =

solutions that deal in high volumes of data processing, this demand can =
only=20
increase.</P>
<P>That=E2=80=99s why it=E2=80=99s so very surprising to see David =
Heinemeier Hansson <A=20
href=3D"http://www.loudthinking.com/posts/7-multi-core-hysteria-and-the-t=
hread-confusion">dismiss=20
the whole notion out of hand regarding Rails.</A> His argument seems to =
be that=20
Rails already scales to multiple cores in the same way it scales to =
multiple=20
machines, via UNIX process distribution. After all, isn=E2=80=99t this =
the very crux of=20
=E2=80=9CShare Nothing?=E2=80=9D</P>
<P>But the math says something different, because for a single server =
=E2=80=9CShare=20
Nothing=E2=80=9D doesn=E2=80=99t really exist. Even if the processes =
don=E2=80=99t share state, they=20
share the same pool of resources (e.g., system memory, disk and system =
bus=20
bandwidth). Each one can be a serious issue. Consider a deployed Rails=20
application, where each Rails process (running mongrel) weighs in at =
about 200=20
real megabytes of RAM. If we wanted to take advantage of 8 cores, =
we=E2=80=99d be using=20
a <EM>bare minimum</EM> of 1.6gb of memory=E2=80=93not to mention an =
even more dire=20
situation with system bus bandwidth. With a dual-processor setup, you =
could=20
easily see a machine with 16gb of RAM being resource starved.</P>
<P>David talks about welcoming a 64-core chip, but the truth is that =
Rails=E2=80=99s=20
process-level concurrency can already barely accommodate today=E2=80=99s =
top of the=20
line. Within 6 months we will see machines with 32 and possibly 64 cores =
in a=20
dual-processor configuration as a top of the line, and today=E2=80=99s =
best being=20
commonplace. What scales for many machines doesn=E2=80=99t scale for =
one.</P>
<P>It isn=E2=80=99t surprising that many Ruby libraries prefer to scale =
at the process=20
level. The argument for process-level concurrency is a good one: =
It=E2=80=99s dead=20
simple. We=E2=80=99re already doing it, and it=E2=80=99s worked fairly =
well up until now. It=E2=80=99s=20
also simple because some of the many Ruby libraries that Rails uses =
don=E2=80=99t play=20
nice with threads. Changing that requires a lot of work, and =
it=E2=80=99s work that=20
wouldn=E2=80=99t immediately yield up any new features. It=E2=80=99s a =
lot of work for a status=20
quo, which can be hard to invest time in.</P>
<P>The most important thing to remember when thinking about the future =
of Ruby=20
is that just because we don=E2=80=99t have convenient methods for =
threading Ruby=20
<EM>today</EM>, it doesn=E2=80=99t mean we shouldn=E2=80=99t explore all =
the possible avenues.=20
YARV, JRuby, or Rubinius may come along any day and blow us away with =
completely=20
new ways to think about working with concurrency. If Rails is ready for =
this, it=20
can continue to be on the forefront of web toolkits. If it is not it =
will=20
rapidly fall behind, because ignoring the problem at this stage is =
ignoring=20
problems that well-funded startups have already encounterd.</P>
<P>Talking to some major Rails developers for 5 minutes, ideas like =
simultaneous=20
request-processing (something Ezra Zygmuntowicz=E2=80=99s <A=20
href=3D"http://brainspl.at/articles/2006/10/18/merb-is-useable-and-a-gem"=
>Merb</A>=20
already does), parallelized partial rendering, and really crazy =
out-there=20
future-talking ideas like stateful HTTP, or trivial implementations of=20
Comet-like technology were mentioned immediately. Imagine what could be=20
accomplished with a real implementation to play with?</P>
<P>Keep an eye on these new Ruby implementations. The first people to =
really=20
innovate technically with them will have an enormous advantage over =
their=20
competitors. </P>
<DIV class=3Dpost-content-footer></DIV><!-- .post-content-footer =
--></DIV><!-- .post-content --><!-- ISI_LISTEN_STOP -->
<DIV class=3Dpost-footer>
<P><SPAN><!-- AddThis Bookmark Button BEGIN --><A=20
onclick=3D"addthis_url   =3D location.href; addthis_title =3D =
document.title; return addthis_click(this);"=20
href=3D"http://www.addthis.com/bookmark.php" target=3D_blank><IMG =
height=3D16=20
alt=3D"AddThis Social Bookmark Button" =
src=3D"http://s5.addthis.com/button1-bm.gif"=20
width=3D125 border=3D0></A>
<SCRIPT type=3Dtext/javascript>var addthis_pub =3D =
'oreillynetwork';</SCRIPT>

<SCRIPT src=3D"http://s5.addthis.com/js/widget.php?v=3D10"=20
type=3Dtext/javascript></SCRIPT>
 <!-- AddThis Bookmark Button END --></SPAN>
<P></P></DIV><!-- .post-footer --></DIV><!-- .post -->
<H3 class=3Dcomments-open-header><A name=3Dcomments></A>Comments</H3>
<FORM id=3Dcomment-form name=3Dcomments_form=20
onsubmit=3D"if (this.bakecookie.checked) rememberMe(this)"=20
action=3Dhttp://www.oreillynet.com/mt/mt-comments.cgi =
method=3Dpost><INPUT=20
type=3Dhidden value=3D1 name=3Dstatic> <INPUT type=3Dhidden =
value=3D20518 name=3Dentry_id>=20
<DIV>
<DIV style=3D"FLOAT: left; MARGIN-RIGHT: 10px"><LABEL=20
for=3Dcomment-author>Name</LABEL><BR><SPAN class=3Dform-field><INPUT=20
id=3Dcomment-author size=3D15 name=3Dauthor></SPAN> </DIV>
<DIV style=3D"FLOAT: left; MARGIN-RIGHT: 10px"><LABEL=20
for=3Dcomment-url>Website</LABEL><BR><SPAN class=3Dform-field><INPUT =
id=3Dcomment-url=20
size=3D25 name=3Durl></SPAN> </DIV>
<DIV style=3D"FLOAT: left; TEXT-ALIGN: center"><LABEL=20
for=3Dcomment-bake-cookie>Save?</LABEL><BR><INPUT =
id=3Dcomment-bake-cookie=20
onclick=3D"if (!this.checked) forgetMe(document.comments_form)" =
type=3Dcheckbox=20
value=3D1 name=3Dbakecookie></SPAN> </DIV>
<DIV style=3D"CLEAR: both; PADDING-BOTTOM: 10px"></DIV></DIV>
<DIV><LABEL for=3Dcomment-email>Email Address =
(required)</LABEL><BR><SPAN=20
class=3Dform-field><INPUT id=3Demail size=3D25 name=3Demail></SPAN> =
</DIV>
<DIV style=3D"CLEAR: both; PADDING-BOTTOM: 10px"></DIV>
<DIV><LABEL for=3Dcomment-text>Comments (you may use HTML tags for=20
style)</LABEL><BR><SPAN class=3Dform-field><TEXTAREA id=3Dcomment-text =
style=3D"WIDTH: 98%" name=3Dtext rows=3D6 cols=3D30></TEXTAREA></SPAN>=20
</DIV>
<DIV class=3Dform-row style=3D"MARGIN-TOP: 10px" align=3Dcenter><INPUT =
id=3Dcomment-preview accessKey=3Dv =
onclick=3D"preview_comment(document.getElementById('comment-text').value)=
;" type=3Dbutton value=3DPreview name=3Dpreview>=20
<INPUT id=3Dcomment-post accessKey=3Ds type=3Dsubmit value=3DPost =
name=3Dpost>=20
</DIV></FORM>
<SCRIPT =
type=3Dtext/javascript>individualArchivesOnLoad(commenter_name);</SCRIPT>=


<DIV id=3Dcomments>
<DIV class=3Dcomment id=3Dcomment-705853><A id=3Dc705853></A>
<P>I'm afraid I'm with DHH. Memory is cheap and working set size is a =
matter for=20
the operating system - as should the issue of multi-core and anything to =
do with=20
concurrency.</P>
<P>Fundamentally the most limited resource is human brainpower. =
Introducing=20
threading into any program creates problems - because humans just don't =
think=20
like that.</P>
<P>You get the biggest pool of programmers available to you if you can =
just=20
assume that you aren't sharing anything with anybody for any reason. =
That is why=20
the process was invented in the first place - to help eliminate screw =
ups.</P>
<P>Now if the Unix process abstraction isn't what we need in the 21st =
Century,=20
then go revisit that. But whatever you do, don't make it something an=20
application programmer has to worry about. </P>
<DIV class=3Dcomment-footer><STRONG><A title=3Dhttp://www.3spoken.co.uk=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D70=
5853">Neil=20
Wilson</A></STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-705853">June=20
7, 2007 08:43 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-706375><A id=3Dc706375></A>
<BLOCKQUOTE>Now if the Unix process abstraction isn't what we need in =
the 21st=20
  Century, then go revisit that. But whatever you do, don't make it =
something an=20
  application programmer has to worry about. </BLOCKQUOTE>
<P>Full ACK. Concurrency is an extremely hard problem to get right, and =
I much=20
prefer to let the programming language, operating system, etc handle it =
for me.=20
Much less likely to end up with awful dilemmas that way. :)</P>
<DIV class=3Dcomment-footer><STRONG><A =
title=3Dhttp://metametta.blogspot.com=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D70=
6375">Gregory</A></STRONG>=20
| <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-706375">June=20
7, 2007 08:55 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-706381><A id=3Dc706381></A>
<P>Hm, my mongrels are just over 60MB or so. </P>
<P>Never understood why a Rails process had to be so huge. Getting it =
down to=20
say, 20MB or so, would be a huge improvement.</P>
<DIV class=3Dcomment-footer><STRONG><A title=3Dhttp://tanga.com=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D70=
6381">Joe</A></STRONG>=20
| <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-706381">June=20
7, 2007 08:56 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-706388><A id=3Dc706388></A>
<P>By the way, nice post David, hope to see more like these...</P>
<DIV class=3Dcomment-footer><STRONG><A =
title=3Dhttp://metametta.blogspot.com=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D70=
6388">Gregory</A></STRONG>=20
| <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-706388">June=20
7, 2007 08:56 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-706470><A id=3Dc706470></A>
<P>Excellent article. It makes me happy to see sane, levelheaded =
discussion=20
about the matter.</P>
<DIV class=3Dcomment-footer><STRONG>James Herdman</STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-706470">June=20
7, 2007 09:02 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-706923><A id=3Dc706923></A>
<P>I'm afraid I disagree with DHH on this issue, although I have to =
admit I'm=20
confused about what he's talking about when he uses the word =
"processes". Is he=20
talking about green threads? Fork? I don't know.</P>
<P>In any case, after reading even a portion of "Programming Erlang" =
I've=20
realized a couple of things. First, we're thinking about COP wrong - =
it's=20
possible (and better, and easier) without native threads.</P>
<P>Second, we should try to make a language that scales up as well as =
out. I=20
mean, why toss more hardware at a problem, when you're not taking =
advantage of=20
the hardware you have? That, or avoid having to jump through lots of =
extra hoops=20
to do so.</P>
<P>Consider <A href=3D"http://www.sics.se/~joe/apachevsyaws.html">this=20
benchmark</A> of YAWS (an Erlang web server) vs Apache. In a world where =
PM's=20
and programmers constantly question the scalability of various web =
frameworks,=20
we need to look at Erlang's implementation and seriously consider if =
we've all=20
been thinking about the issue from the wrong angle all this time.</P>
<P>Anyway, my general feeling is that we're rationalizing the lack of =
SMP=20
support in Ruby (and other languages), instead trying to solve it.</P>
<DIV class=3Dcomment-footer><STRONG>Daniel Berger</STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-706923">June=20
7, 2007 09:35 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-707081><A id=3Dc707081></A>
<P>Neil Wilson said:<BR>
<BLOCKQUOTE>Memory is cheap and working set size is a matter for the =
operating=20
  system - as should the issue of multi-core and anything to do with=20
concurrency.</BLOCKQUOTE>
<P></P>
<P>First of all, the kind of memory we're talking about here (and the =
boards to=20
handle it) <B>are not cheap</B> (for example, look at <A=20
href=3D"http://castle.pricewatch.com/s/search.asp?s=3D4gb+DDR+ECC+RAM+2+x=
+2GB&amp;srt=3Dt&amp;mi=3D0&amp;m=3D&amp;view=3D">the=20
prices of 4gb of ram in 2-module configurations</A>), they can easily =
make up a=20
sizable chunk of the cost for a server. And even if memory is cheap, =
system bus=20
bandwidth is growing at a much sower rate than the other aspects of =
modern=20
server hardware.</P>
<P>Second of all, I'm not saying we should engage in some kind of =
radical=20
rewrite of Rails or other Ruby libraries. I'm saying we should start to =
make our=20
apps thread safe so that when a good ruby implementation that does =
threading=20
right comes along, it will result in a "free" upgrade. In the specific =
case of=20
Rails, let's make ActiveRecord thread safe, and people writing new =
libraries=20
like mongrel should think about concurrency as well.</P>
<P>I'm surprised my opinion is at all controvesial. To me, it seems like =
just=20
reading the writing on the front of a swiftly approaching train. :)</P>
<DIV class=3Dcomment-footer><STRONG><A =
title=3Dhttp://kirindave.tumblr.com=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D70=
7081">Dave=20
Fayram</A></STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-707081">June=20
7, 2007 10:38 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-707229><A id=3Dc707229></A>
<P>Memory arrays might not be cheap at the moment, but they'll get =
cheaper once=20
you have 64 core chips demanding service.</P>
<P>The arguments you put forward are the same ones for threads in the =
first=20
place - it is machine optimal. But as we have seen machines get faster - =
very=20
quickly.</P>
<P>What doesn't get faster or smarter is the brain power of your average =
human=20
grunt programmer. It is that we need to optimise towards. Hardware will =
become=20
fast enough and cheap enough as the need arises, but will require a =
different=20
programming technique. That technique needs to be simple if programmers =
are to=20
master it effectively.</P>
<P>For me threads always were a backward step. That Rails is not =
thread-safe is=20
actually one of its benefits - it stops the premature optimisation in a =
single=20
program that seems so popular amongst those who have grown up with =
easily=20
available threading. </P>
<P>Modern programmers need to reacquaint themselves with the process, =
and the=20
delights of not having to worry about whether there is some other =
execution=20
context twiddling with your object attributes.</P>
<P>I'd write a 'threads considered harmful' piece, but <A=20
href=3D"http://www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.html"=
>others</A>=20
have done it much more eloquently than I ever could.</P>
<DIV class=3Dcomment-footer><STRONG><A title=3Dhttp://www.3spoken.co.uk=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D70=
7229">Neil=20
Wilson</A></STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-707229">June=20
7, 2007 11:13 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-707467><A id=3Dc707467></A>
<P>I'm not sure that YAWS benchmark is relevant to anything in the real =
world.=20
On what hardware could processing 80,000 requests *simultaneously* be =
useful?=20
</P>
<P>You don't even have to look far past the network: Divide a gigabit =
connection=20
up 80,000 ways and you're serving content to each user at a blistering =
1.5KB/s.=20
Hello, 1990. Oh, how I've missed you and your bad hair.</P>
<DIV class=3Dcomment-footer><STRONG>Rick</STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-707467">June=20
7, 2007 11:45 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-707788><A id=3Dc707788></A>
<P>What kind of operating system are you using that fork() and COW =
memory pages=20
can't get you processes that can run on multiple cores without using =
hundreds of=20
megabytes apiece?</P>
<DIV class=3Dcomment-footer><STRONG><A title=3Dhttp://www.onlamp.com/=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D70=
7788">chromatic</A></STRONG>=20
| <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-707788">June=20
7, 2007 01:03 PM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-707790><A id=3Dc707790></A>
<P>Neil Wilson:<BR>
<BLOCKQUOTE>Memory arrays might not be cheap at the moment, but they'll =
get=20
  cheaper once you have 64 core chips demanding service.</BLOCKQUOTE>
<P></P>
<P>As I said, the problem exists <I>today</I>. It's not some "Memory =
will be=20
cheap enough soon" situation. When I was working at Mog, we deliberately =
chose=20
our servers with the amount of ram it had and the amount of ram <EM>it =
could=20
use</EM> in mind. The former need not be higher than the later, and so =
we chose=20
systems with fewer cores than was financially possible.</P>
<BLOCKQUOTE>The arguments you put forward are the same ones for threads =
in the=20
  first place - it is machine optimal. But as we have seen machines get =
faster -=20
  very quickly.</BLOCKQUOTE>
<P>I am not arguing for any specific concurrency paradigm. I am arguing =
for=20
concurrency-safe programming. These practices dovetail nicely with the =
list of=20
best practices for object oriented coding anyways (e.g., "Minimize use =
of global=20
state"). </P>
<BLOCKQUOTE>What doesn't get faster or smarter is the brain power of =
your=20
  average human grunt programmer. It is that we need to optimise =
towards.=20
  Hardware will become fast enough and cheap enough as the need arises, =
but will=20
  require a different programming technique. That technique needs to be =
simple=20
  if programmers are to master it effectively.</BLOCKQUOTE>
<P>I don't like talking in terms like this, I find it extremely =
patronizing. If=20
a programmer cannot perform, then they will lose their job to someone =
who can.=20
Again, I reiterate I am not saying, "Write a threaded rails". I'm =
saying, "Write=20
a thread-safe rails." As it stands, I can't even cleanly fork() a rails =
process,=20
or use multithreading within it. </P>
<BLOCKQUOTE>Modern programmers need to reacquaint themselves with the =
process,=20
  and the delights of not having to worry about whether there is some =
other=20
  execution context twiddling with your object attributes.</BLOCKQUOTE>
<P>And if Rubinius suddenly offers erlang-style concurrency, Rails will =
need a=20
ton of work to take advantage of it. You're caught up on the word =
thread,=20
assuming I am too. Please don't be.</P>
<DIV class=3Dcomment-footer><STRONG><A =
title=3Dhttp://kirindave.tumblr.com=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D70=
7790">Dave=20
Fayram</A></STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-707790">June=20
7, 2007 01:09 PM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-707793><A id=3Dc707793></A>
<BLOCKQUOTE>What kind of operating system are you using that fork() and =
COW=20
  memory pages can't get you processes that can run on multiple cores =
without=20
  using hundreds of megabytes apiece?</BLOCKQUOTE>
<P>It's not the operating system. It's Ruby's garbage collector. Since =
it sweeps=20
the whole object space marking objects, it defeats any kind of CoW =
scheme you=20
might expect to work, since it writes to those pages. </P>
<DIV class=3Dcomment-footer><STRONG><A =
title=3Dhttp://kirindave.tumblr.com=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D70=
7793">Dave=20
Fayram</A></STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-707793">June=20
7, 2007 01:12 PM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-708089><A id=3Dc708089></A>
<P>@Dave, that's a good point--but it's not terribly difficult to keep =
object GC=20
flags in their own memory pages (assuming a well-factored GC =
system).</P>
<P>Even so, I remain unconvinced that the largest scalability problem of =
most=20
server applications is CPU time.</P>
<DIV class=3Dcomment-footer><STRONG><A title=3Dhttp://www.onlamp.com/=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D70=
8089">chromatic</A></STRONG>=20
| <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-708089">June=20
7, 2007 02:30 PM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-708127><A id=3Dc708127></A>
<P>Rubinius's separate, 2-space GC will handle CoW in a sane way. Watch =
for it=20
in the fall at a Ruby dealer near you.</P>
<DIV class=3Dcomment-footer><STRONG><A =
title=3Dhttp://blog.evanweaver.com=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D70=
8127">evan</A></STRONG>=20
| <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-708127">June=20
7, 2007 02:37 PM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-708268><A id=3Dc708268></A>
<P>The fundamental problem is functional vs. imperative programming=20
languages.</P>
<P>Imperative programming languages make it easy to write sequential =
programs=20
and hard to write parallel programs.</P>
<P>Purely functional programming languages make it hard to write =
sequential=20
programs (monads), but easy to write parallel programs.</P>
<P>Ruby has some functional programming features, but it still relies =
heavily on=20
state which makes automatic parallelization difficult.</P>
<P>Multicore processors will drive the adoption of functional =
programming=20
languages like Erlang and Haskell.</P>
<DIV class=3Dcomment-footer><STRONG>Tim Olsen</STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-708268">June=20
7, 2007 03:25 PM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-708275><A id=3Dc708275></A>
<P>Rails is, by and large, threadsafe in production mode. The parts of =
the=20
framework which aren't are isolated to actionpack, mostly in the caching =
code.=20
Far from needing a 'ton of work', rails is already mostly there.</P>
<P>However, at present there's essentially no point spending time making =
those=20
changes. Green threads and blocking IO make for shitty concurrent =
performance,=20
and while merb may well be faster than rails, I've yet to see any =
convincing=20
real world profiling reports which prove that that's just because of =
'thread=20
safety'. Threads aren't magic beans that give you a magic performance =
boost.</P>
<P>Until we have a ruby VM with 'real' threads, DB drivers which do =
async IO,=20
and a GC which is compatible with all of the above, making rails =
threadsafe is a=20
wasted effort. Once we have those things, or they're clearly just around =
the=20
corner, I'll be happy to work with concerned individuals to get their =
patches=20
merged.</P>
<DIV class=3Dcomment-footer><STRONG><A title=3Dhttp://www.koziarski.net/ =

href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D70=
8275">Michael=20
Koziarski</A></STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-708275">June=20
7, 2007 03:31 PM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-708720><A id=3Dc708720></A>
<P>I think what we need to do is, step back and take Dave Hansson's=20
pronouncements about databases and hardware architecture with a grain of =
salt. I=20
would recommend a cowlick, but that would be plain rude. Dave Hansson is =
a=20
marketing guy. Stop treating him like you would treat Joe Armstrong or =
Rob Pike=20
or something. </P>
<P>Dave doesn't understand hardware and the unix process model, calls =
the Ruby=20
interpreter "the compiler", refers to a relational database system as a =
"big=20
hash" and so on and so forth.</P>
<P>Dave H created rails, using some really crufty PHP like code, and it =
took=20
off. It doesn't mean he knows something on concurrency that people like =
Joe=20
Armstrong don't. Stop treating him like he is an expert on everything. =
Outside=20
of rails, he's mostly talking out of his umm .. you know.. A$$?</P>
<P>Sometimes we give people too much credit in unrelated areas of =
expertise.=20
It's like George Cloony talking out of his ass on geo political issues =
or a=20
basketball player pontificating about morality just cuz he got picked up =
by the=20
NBA. You know, asking Ja Rule about the significance of the events of =
9/11...=20
Just not gonna happen!</P>
<P>Fame does not an expert make. (groupies not withstanding)</P>
<DIV class=3Dcomment-footer><STRONG>Mike G</STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-708720">June=20
7, 2007 06:15 PM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-709231><A id=3Dc709231></A>
<P>@Mike G</P>
<P>Hahahaha. You may be overstating, but nice counterbalance :)</P>
<DIV class=3Dcomment-footer><STRONG><A =
title=3Dhttp://metametta.blogspot.com=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D70=
9231">Gregory</A></STRONG>=20
| <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-709231">June=20
7, 2007 08:33 PM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-709825><A id=3Dc709825></A>
<P>The biggest problem with this discussion is that it rests on an =
assumption=20
that wasn't tested in reality. The statement that 1.6GB of RAM would be =
used is=20
based on the extremely unlikely mathematics of 8 cores * 200MB.</P>
<P>Until this is actually tried out (rather than arguments about memory =
and=20
CPU), we have no extraordinary proof to back up the extraordinary =
assertion...=20
which, if true, does indeed prove DHH wrong.</P>
<P>If the extraordinary assertion is wrong, and the concrete measurement =
of the=20
actual value is closer to a much more reasonable number, then no time =
would have=20
been wasted by the discussion you can see by scrolling up.</P>
<P>My ordinary assertion, based on running multiple copies of other =
programs, is=20
that the OS is capable of sharing memory. For example, glibc is present =
in=20
nearly every program that runs on Unix, yet the hundred or so processes =
do not=20
incur a 100 * 20MB overhead (2GB RAM!).<BR></P>
<DIV class=3Dcomment-footer><STRONG>steve</STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-709825">June=20
8, 2007 12:21 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-710960><A id=3Dc710960></A>
<P>Steve, I was the sole developer for Ma.gnolia.com up until its =
launch, and I=20
worked with Lucas Carlson to launch Mog.com and maintain it. I've also =
consulted=20
for several people launching or maintaining Rails apps. I have deployed =
and=20
profiled apps running on multi-core hardware, so I've seen these effects =
in=20
action.</P>
<P>Michael Koziarski knows more about the rails codebase than I do, but =
I stand=20
by my numbers in terms of where apps often end up. I've also gone and =
asked=20
several prominent Rails developers what ranges their Rails responders =
fall into.=20
I did a fair amount of homework before settling on 200mb, which is close =
ot my=20
personal experienes and falls into the 150-250 range that most people =
with=20
nontrivial apps quote.</P>
<P>It depends on a variety of factors, of course, but 200mb for a =
complex app=20
with Rmagick isn't unreasonable at all. You <I>can</I> save some memory =
by=20
forking, but that amount gradually goes down, and forking freaks =
ActiveRecord=20
out. </P>
<P>Finally, Steve, the OS <B>is</B> sharing memory for libraries as=20
intelligently as it can. It will give every process the same copy of the =

read-only pages associated with the imagemagick libraries, for example. =
However,=20
This is a small fraction of where the memory goes. One of the problems =
with=20
interpreters is that they can't automatically share memory as =
efficiently as=20
compiled code can, since the system is so optimized for the compiled =
code=20
case.<BR></P>
<DIV class=3Dcomment-footer><STRONG><A =
title=3Dhttp://kirindave.tumblr.com=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D71=
0960">Dave=20
Fayram</A></STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-710960">June=20
8, 2007 07:44 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-710996><A id=3Dc710996></A>
<BLOCKQUOTE>It depends on a variety of factors, of course, but 200mb for =
a=20
  complex app with Rmagick isn't unreasonable at all. </BLOCKQUOTE>
<P>Is that taking into account the memory leaks or no? :)</P>
<DIV class=3Dcomment-footer><STRONG><A =
title=3Dhttp://metametta.blogspot.com=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D71=
0996">Gregory</A></STRONG>=20
| <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-710996">June=20
8, 2007 07:55 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-711115><A id=3Dc711115></A>
<P>All I can say is proove it. Stop spewing out FUD and show me some =
real=20
evidence. So a bunch of people are creating some hysteria over =
multi-core, well,=20
it just makes them that, a bunch of people creating hysteria. That is =
all, end=20
of story.</P>
<P>I ask you what benchmarks did you use to make sure your single core =
processor=20
was being used efficiently? How do you know that a single core was your=20
performance bottlenect? Did a big company with a big marketing budget =
tell you=20
that you needed more cores? So, what makes you think you can now all of =
the=20
sudden be critical of raw computing power just because you have two, or =
more=20
cores?</P>
<P>Please people, don't fall for this FUD. Do some real investigation =
and=20
benchmarking.</P>
<DIV class=3Dcomment-footer><STRONG><A title=3Dhttp://www.calpoly.edu=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D71=
1115">John=20
Pywtorak</A></STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-711115">June=20
8, 2007 09:13 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-711364><A id=3Dc711364></A>
<P>I have done a lot of client work, and I routinely see Mongrels in the =
200 to=20
300MB range. The 'record' so far was on a consultation for a California =
company,=20
that had 13 Mongrel instances each taking 305 to 320MB of RAM.<BR>This =
is not=20
Mongrel's fault, of course.. it's the fault of the Rails programmers =
involved.=20
However, Ruby's GC behavior is not well understood by Rails developers,=20
generally, and it is easy for inexperienced coders to get into deep =
water.</P>
<P>BackgrounDRb is a common source of trouble. While that is a solid and =

excellent library, it must be used with care to avoid preventing the GC =
from=20
collecting your objects.</P>
<DIV class=3Dcomment-footer><STRONG>Wilson Bilkovich</STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-711364">June=20
8, 2007 10:18 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-711367><A id=3Dc711367></A>
<P>Here is a snapshot of typical RAM usage for one of the Mongrel's =
running <A=20
href=3D"http://mog.com/">http://mog.com/</A> on a 4 core machine.</P>
<P>RAM used: 219184 kB</P>
<DIV class=3Dcomment-footer><STRONG><A title=3Dhttp://mog.com/=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D71=
1367">Lucas=20
Carlson</A></STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-711367">June=20
8, 2007 10:19 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-711411><A id=3Dc711411></A>
<P>Mongrels for <A =
href=3D"http://gravatar.com/">http://gravatar.com/</A>=20
consistently stabilize between 200MB and 250MB each. These are on a two =
core=20
machine.</P><PRE>VIRT  RES  SHR DATA COMMAND
257m 251m 3176 249m mongrel_rails
238m 232m 3040 230m mongrel_rails
</PRE>
<P>It's foolish not to use whatever threading capabilities are available =
to us=20
in the framework. Having to start and maintain multiple Rails instances =
where=20
one (thread safe version) could suffice represents additional complexity =
that I=20
would rather do without. Not to mention that the memory overhead is =
real.</P>
<DIV class=3Dcomment-footer><STRONG><A title=3Dhttp://gravatar.com=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D71=
1411">Tom=20
Preston-Werner</A></STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-711411">June=20
8, 2007 10:40 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-711468><A id=3Dc711468></A>
<P>Oh, well if stateful connections will take of - no way to stay on the =
process=20
level. Here is the point in case: <A=20
href=3D"http://blog.fastmail.fm/?p=3D592">http://blog.fastmail.fm/?p=3D59=
2</A></P>
<DIV class=3Dcomment-footer><STRONG>Vlad D</STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-711468">June=20
8, 2007 11:08 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-711486><A id=3Dc711486></A>
<P>In general, my apps run slightly under 200MB when they've been up for =
some=20
amount of time.</P>
<DIV class=3Dcomment-footer><STRONG><A =
title=3Dhttp://www.jeremymcanally.com/=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D71=
1486">Jeremy=20
McAnally</A></STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-711486">June=20
8, 2007 11:19 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-711487><A id=3Dc711487></A>
<P>In general, my apps run slightly under 200MB when they've been up for =
some=20
amount of time.</P>
<DIV class=3Dcomment-footer><STRONG><A =
title=3Dhttp://www.jeremymcanally.com/=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D71=
1487">Jeremy=20
McAnally</A></STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-711487">June=20
8, 2007 11:19 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-720253><A id=3Dc720253></A>
<BLOCKQUOTE>"The first people to really innovate technically with them =
will=20
  have an enormous advantage over their competitors."</BLOCKQUOTE>
<P>Never trust people who try to scare you into behaving like they want. =
This is=20
clearly FUD, and somebody here wants very eagerly be seen as an expert. =
Very bad=20
style.</P>
<DIV class=3Dcomment-footer><STRONG>Anonymous</STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-720253">June=20
10, 2007 01:59 PM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-720576><A id=3Dc720576></A>
<P>Anonymous (if that is your <EM>real name</EM>?)... </P>
<P>My argument is that conceptually, nothing stops rails from taking =
advantage=20
of N-core systems. In fact, conceptually it's in a very good position to =
do=20
that. However, currently its implementation precludes that notion.</P>
<P>I'm not sure how I'm manipulating people to my benefit by suggesting =
we=20
should be improving Rails. I'm also usure how I ended up defending the =
position=20
that we should be writing parallelization threading code by hand. =
Certainly=20
that's not how I feel. I'm advocating making rails thread-agnostic in=20
preparation for ruby implementations that offer true threading (and/or =
better=20
concurrency models).</P>
<DIV class=3Dcomment-footer><STRONG><A =
title=3Dhttp://kirindave.tumblr.com=20
href=3D"http://www.oreillynet.com/mt/mt-comments.cgi?__mode=3Dred;id=3D72=
0576">Dave=20
Fayram</A></STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-720576">June=20
10, 2007 02:41 PM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-722563><A id=3Dc722563></A>
<P>I think 1G RAM always going to be cheaper than 1core+2MB cache.</P>
<P>It's technically really challenging to feed 64 cores with data alone, =
so the=20
first move is to release that 64 core machines, and make them cost =
effective.=20
There will be a lot of Ruby implementations that time to choose =
from.</P>
<DIV class=3Dcomment-footer><STRONG>teki321</STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-722563">June=20
11, 2007 12:52 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-815604><A id=3Dc815604></A>
<P>ditto, for me on mongrel mem usage...</P>
<P>VIRT RES SHR S %CPU %MEM TIME+ COMMAND<BR>217m 165m 8568 S 0 1.0 =
24:43.48=20
mongrel_rails<BR>230m 178m 8568 S 0 1.1 26:32.17 mongrel_rails<BR>289m =
237m 8568=20
S 0 1.5 26:50.59 mongrel_rails</P>
<P>I am exploring deploying under glassfish w/jruby and this<BR>looks =
like it=20
could be an attractive alternative down the road. The rails-integration=20
(goldspike?) code maintains an object pool of Rails instances - so =
scaling means=20
creating more these which I suppose is more efficient memory wise than N =
mongrel=20
processes since large parts of the JVM can be shared? </P>
<P>Anyway, I think rails deployment has a ways to go before it <BR>can =
be=20
considered stupid simple to do. It reminds me of the early days of Java =
app=20
servers where you were always worrying about your server locking up and =
needing=20
a restart.</P>
<P><BR></P>
<DIV class=3Dcomment-footer><STRONG>tom</STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-815604">June=20
22, 2007 05:19 PM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment -->
<DIV class=3Dcomment id=3Dcomment-846914><A id=3Dc846914></A>
<P>Don't forget about people how use cheap hosting services. I guess =
that single=20
server can handle thousands of accounts. Each account can be accessed =
for=20
example ten times per day. Note that PHP won the development market =
taking it=20
from the bottom. So from this point of view, ability to economical use =
of=20
memory, might be very important for RoR to become mainstream web =
development=20
tool.</P>
<P>To use Comet like features, there is no need to put that stuff int o =
RoR. Web=20
server can handle that dirty work very well. Check my fdajax module for =
lighttpd=20
web server.<BR></P>
<DIV class=3Dcomment-footer><STRONG>Grzegorz Daniluk</STRONG> | <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/multicore_hardware_an=
d_the_fut.html#comment-846914">June=20
24, 2007 03:44 AM</A> </DIV><!-- end .comment-footer --></DIV><!-- end =
.comment --></DIV><!-- end #comments --></DIV><!--end #blog -->
<DIV id=3Dsidebar><BR>
<DIV class=3Dsidebar-item>
<H3>Search</H3>
<DIV class=3Dsidebar-item-content>
<FORM id=3Dsearch name=3DsearchForm onsubmit=3DprocessQuery();=20
action=3Dhttp://promosearch.atomz.com/search/promosearch =
method=3Dget><!--  search  --><INPUT type=3Dhidden value=3Dsp1000a5a9 =
name=3Dsp-a>=20
<INPUT type=3Dhidden value=3DISO-8859-1 name=3Dsp-f> <INPUT =
type=3Dhidden value=3Dgeneral=20
name=3Dsp-t> <INPUT type=3Dhidden value=3Dcat name=3Dsp-x-1> <INPUT =
type=3Dhidden=20
name=3Dsp-q-1> <INPUT type=3Dhidden value=3Dcat2 name=3Dsp-x-2> <INPUT =
type=3Dhidden=20
name=3Dsp-q-2> <INPUT type=3Dhidden value=3D25 name=3Dsp-c> <INPUT =
type=3Dhidden value=3Dall=20
name=3Dsp-p> <INPUT type=3Dhidden =
value=3DArticles|Books|Conferences|Other|Weblogs=20
name=3Dsp-k> <INPUT type=3Dhidden name=3Dc> <INPUT type=3Dhidden =
name=3Dp> <INPUT id=3Dsrc=20
accessKey=3Ds maxLength=3D80 size=3D10 name=3Dquery> <INPUT =
type=3Dhidden name=3Dsp-q>&nbsp;<INPUT onclick=3D"return searchverif();" =
type=3Dsubmit value=3DGo name=3Dsearch>=20
</FORM></DIV></DIV>
<DIV class=3Dsidebar-item>
<H3>Categories</H3>
<DIV class=3Dsidebar-item-content>
<UL>
  <LI><A title=3D""=20
  href=3D"http://www.oreillynet.com/ruby/blog/articles/">Articles</A>=20
  <LI><A title=3D"" =
href=3D"http://www.oreillynet.com/ruby/blog/news/">News</A>=20
  <LI><A title=3D""=20
  href=3D"http://www.oreillynet.com/ruby/blog/opinion/">Opinion</A>=20
  <LI><A title=3D""=20
  href=3D"http://www.oreillynet.com/ruby/blog/reviews/">Reviews</A>=20
  <LI><A title=3D""=20
  href=3D"http://www.oreillynet.com/ruby/blog/technical/">Technical</A>=20
</LI></UL></DIV></DIV>
<DIV class=3Dsidebar-item>
<H3>Recent Articles</H3>
<DIV class=3Dsidebar-item-content>
<UL>
  <LI><A=20
  =
href=3D"http://www.oreillynet.com/pub/a/ruby/2008/01/14/shoes-meets-merb-=
interfacing-a-gtk2-front-end-and-a-rails-web-service.html">Shoes=20
  Meets Merb: Driving a GUI App through Web Services in Ruby</A>
  <LI><A=20
  =
href=3D"http://www.oreillynet.com/pub/a/ruby/2008/01/02/cookin-with-ruby-=
on-rails---integration-tests.html">Cookin'=20
  with Ruby on Rails - Integration Tests</A>
  <LI><A=20
  =
href=3D"http://www.oreillynet.com/pub/a/ruby/2007/12/18/creating-games-in=
-ruby-part-2.html">Creating=20
  Games in Ruby (Part 2)</A>
  <LI><A=20
  =
href=3D"http://www.oreillynet.com/pub/a/ruby/2007/12/04/creating-games-in=
-ruby.html">Creating=20
  Games in Ruby (Part 1)</A>
  <LI><A=20
  =
href=3D"http://www.oreillynet.com/pub/a/ruby/2007/12/04/building-mashups-=
in-rails.html">Building=20
  Mashup-Friendly Sites in Rails</A></LI></UL></DIV>
<DIV class=3Dsidebar-item-footer></DIV></DIV><!-- <h2>Recent =
Articles</h2>=0A=
<ul>=0A=
<li><a =
href=3D"http://radar.oreilly.com/archives/2005/12/ruby_book_sales_surpass=
_python.html">Ruby Book Sales Surpass Python</a></li>=0A=
<li><a =
href=3D"http://www.oreillynet.com/pub/a/network/2005/08/30/ruby-rails-dav=
id-heinemeier-hansson.html">Ruby on Rails: An Interview with David =
Heinemeier Hansson></a></li>=0A=
<li><a =
href=3D"http://www.onjava.com/pub/a/onjava/2005/11/16/ruby-the-rival.html=
">Ruby the Rival (to Java)</a></li>=0A=
<li><a =
href=3D"http://www.xml.com/pub/a/2005/11/09/rexml-processing-xml-in-ruby.=
html">REXML: Processing XML in Ruby</a></li>=0A=
<li><a =
href=3D"http://www.onlamp.com/pub/a/onlamp/2005/10/13/what_is_rails.html"=
>What Is Ruby on Rails</a></li>=0A=
<li><a =
href=3D"http://www.onlamp.com/pub/a/onlamp/2004/06/24/pragmatic_programme=
rs.html">The Pragmatic Programmers Interview</a></li>=0A=
<li><a =
href=3D"http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html">Rolling=
 with Ruby on Rails</a></li>=0A=
<li><a =
href=3D"http://www.onlamp.com/pub/a/onlamp/2005/03/03/rails.html">Rolling=
 with Ruby on Rails, Part 2</a></li>=0A=
<li><a =
href=3D"http://www.onlamp.com/pub/a/onlamp/2005/06/09/rails_ajax.html">Aj=
ax on Rails</a></li> =0A=
</ul> -->
<DIV class=3Dsidebar-item>
<H3>Related Books</H3>
<DIV class=3Dsidebar-item-content>
<UL>
  <LI><A =
href=3D"http://www.oreilly.com/catalog/0974514055/index.html">Programming=
=20
  Ruby, Second Edition</A>=20
  <LI><A href=3D"http://www.oreilly.com/catalog/ruby/index.html">Ruby in =
a=20
  Nutshell</A>=20
  <LI><A =
href=3D"http://www.oreilly.com/catalog/097669400X/index.html">Agile Web=20
  Development with Rails</A>=20
  <LI><A =
href=3D"http://www.oreilly.com/catalog/0976694077/index.html">Best of=20
  Ruby Quiz</A>=20
  <LI><A =
href=3D"http://www.oreilly.com/catalog/0976694093/index.html">Java to=20
  Ruby</A> </LI></UL></DIV></DIV>
<DIV class=3Dsidebar-item>
<H3>Archives</H3>
<DIV class=3Dsidebar-item-content>
<DIV style=3D"MARGIN-BOTTOM: 6px"><EM>2008</EM><BR><A=20
href=3D"http://www.oreillynet.com/ruby/blog/2008/01/">1</A> </DIV>
<DIV style=3D"MARGIN-BOTTOM: 6px"><EM>2007</EM><BR><A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/01/">1</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/02/">2</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/03/">3</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/04/">4</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/05/">5</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/06/">6</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/07/">7</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/08/">8</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/09/">9</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/10/">10</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/11/">11</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2007/12/">12</A> </DIV>
<DIV style=3D"MARGIN-BOTTOM: 6px"><EM>2006</EM><BR><A=20
href=3D"http://www.oreillynet.com/ruby/blog/2006/01/">1</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2006/02/">2</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2006/03/">3</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2006/04/">4</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2006/05/">5</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2006/06/">6</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2006/07/">7</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2006/08/">8</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2006/09/">9</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2006/10/">10</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2006/11/">11</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2006/12/">12</A> </DIV>
<DIV style=3D"MARGIN-BOTTOM: 6px"><EM>2005</EM><BR><A=20
href=3D"http://www.oreillynet.com/ruby/blog/2005/01/">1</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2005/02/">2</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2005/03/">3</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2005/04/">4</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2005/05/">5</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2005/06/">6</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2005/08/">8</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2005/09/">9</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2005/10/">10</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2005/11/">11</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2005/12/">12</A> </DIV>
<DIV style=3D"MARGIN-BOTTOM: 6px"><EM>2004</EM><BR><A=20
href=3D"http://www.oreillynet.com/ruby/blog/2004/01/">1</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2004/02/">2</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2004/03/">3</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2004/04/">4</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2004/05/">5</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2004/06/">6</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2004/07/">7</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2004/08/">8</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2004/09/">9</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2004/10/">10</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2004/11/">11</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2004/12/">12</A> </DIV>
<DIV style=3D"MARGIN-BOTTOM: 6px"><EM>2003</EM><BR><A=20
href=3D"http://www.oreillynet.com/ruby/blog/2003/01/">1</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2003/02/">2</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2003/03/">3</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2003/04/">4</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2003/05/">5</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2003/06/">6</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2003/07/">7</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2003/08/">8</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2003/09/">9</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2003/10/">10</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2003/11/">11</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2003/12/">12</A> </DIV>
<DIV style=3D"MARGIN-BOTTOM: 6px"><EM>2002</EM><BR><A=20
href=3D"http://www.oreillynet.com/ruby/blog/2002/05/">5</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2002/06/">6</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2002/07/">7</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2002/08/">8</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2002/09/">9</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2002/10/">10</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2002/11/">11</A> <A=20
href=3D"http://www.oreillynet.com/ruby/blog/2002/12/">12</A> =
</DIV></DIV>
<DIV class=3Dsidebar-item-footer></DIV></DIV>
<DIV class=3Dsidebar-item>
<H3>Site Feeds</H3>
<DIV class=3Dsidebar-item-content>
<UL>
  <LI><A href=3D"http://www.oreillynet.com/ruby/blog/atom.xml">Atom =
1.0</A>=20
  <LI><A href=3D"http://www.oreillynet.com/ruby/blog/index.xml">RSS =
2.0</A>=20
</LI></UL></DIV>
<DIV class=3Dsidebar-item-footer></DIV></DIV></DIV><!-- end #sidebar -->
<DIV id=3Dskyscraper>
<STYLE type=3Dtext/css>.blog-ad {
	PADDING-TOP: 10px; BACKGROUND-COLOR: #eee; TEXT-ALIGN: center
}
</STYLE>

<DIV class=3Dblog-ad><IMG style=3D"PADDING-BOTTOM: 10px" =
alt=3DAdvertisement=20
src=3D"http://www.oreillynet.com/images/ads/advertisement.gif"> <BR>
<DIV class=3Dadtag>
<SCRIPT language=3DJavaScript type=3Dtext/javascript>=0A=
      var ord =3D (ord !=3D null ? ord : Math.random()*10000000000000000 =
);=0A=
      document.write('<script language=3D"JavaScript" =
src=3D"http://ad.doubleclick.net/adj/ttm.ruby/weblog;tile=3D2;sz=3D160x60=
0;ord=3D' + ord + '?" type=3D"text/javascript"><\/script>');=0A=
   </SCRIPT>
</DIV><BR>
<DIV class=3Dadtag>
<SCRIPT language=3DJavaScript type=3Dtext/javascript>=0A=
      var ord =3D (ord !=3D null ? ord : Math.random()*10000000000000000 =
);=0A=
      document.write('<script language=3D"JavaScript" =
src=3D"http://ad.doubleclick.net/adj/ttm.ruby/weblog;tile=3D3;sz=3D160x60=
0;ord=3D' + ord + '?" type=3D"text/javascript"><\/script>');=0A=
   </SCRIPT>
</DIV></DIV></DIV>
<DIV style=3D"CLEAR: both; PADDING-TOP: 1px"></DIV></DIV><!-- end =
#page-content -->
<DIV id=3Dfooter>
<P align=3Dcenter><A=20
href=3D"http://www.oreillynet.com/pub/a/mediakit/contact.html">Contact =
Us</A> | <A=20
href=3D"http://www.oreillynet.com/pub/a/mediakit/adcontact.html">Advertis=
e with=20
Us</A> | <A =
href=3D"http://www.oreillynet.com/pub/a/mediakit/privacy.html">Privacy=20
Policy</A> | <A href=3D"http://press.oreilly.com/">Press Center</A> | <A =

href=3D"http://jobs.oreilly.com/">Jobs</A> </P>
<P align=3Dcenter>Weblog authors are solely responsible for the content =
and=20
accuracy of their weblogs, including opinions they express, <BR>and =
O=E2=80=99Reilly=20
Media, Inc., disclaims any and all liability for that content, its =
accuracy, and=20
opinions it may contain.</P>
<P align=3Dcenter><A =
href=3D"http://creativecommons.org/licenses/by-nc-sa/2.5/"><IMG=20
height=3D31 alt=3D"Creative Commons License" hspace=3D4=20
src=3D"http://creativecommons.org/images/public/somerights.gif" =
width=3D88=20
align=3Dmiddle border=3D0></A> This work is licensed under a <A=20
href=3D"http://creativecommons.org/licenses/by-nc-sa/2.5/">Creative =
Commons=20
License</A>.</P><!--<rdf:RDF xmlns=3D"http://web.resource.org/cc/" =0A=
         xmlns:rdf=3D"http://www.w3.org/1999/02/22-rdf-syntax-ns#">=0A=
    <License   =
rdf:about=3D"http://creativecommons.org/licenses/by-nc-sa/2.5/">=0A=
        <permits   =
rdf:resource=3D"http://web.resource.org/cc/Reproduction"/>=0A=
        <permits   =
rdf:resource=3D"http://web.resource.org/cc/Distribution"/>=0A=
        <requires  rdf:resource=3D"http://web.resource.org/cc/Notice"/>=0A=
        <requires  =
rdf:resource=3D"http://web.resource.org/cc/Attribution"/>=0A=
        <prohibits =
rdf:resource=3D"http://web.resource.org/cc/CommercialUse"/>=0A=
        <permits   =
rdf:resource=3D"http://web.resource.org/cc/DerivativeWorks"/>=0A=
        <requires  =
rdf:resource=3D"http://web.resource.org/cc/ShareAlike"/>=0A=
    </License>=0A=
</rdf:RDF>-->
<P></P>
<P align=3Dcenter>For problems or assistance with this site, email <A=20
href=3D"mailto:help@oreillynet.com">help@oreillynet.com</A></P></DIV><!--=
 hitbox --><!-- JLW Hitbox --><!--WEBSIDESTORY CODE HBX1.0 =
(Universal)--><!--COPYRIGHT 1997-2004 WEBSIDESTORY,INC. ALL RIGHTS =
RESERVED. U.S.PATENT No. 6,393,479B1. MORE INFO:http://websidestory.com =
/ privacy-->
<SCRIPT language=3Djavascript type=3Dtext/javascript>=0A=
        var _hbEC=3D0,_hbE=3Dnew Array;function =
_hbEvent(a,b){b=3D_hbE[_hbEC++]=3Dnew Object();b._N=3Da;b._C=3D0;return =
b;}=0A=
    var =
hbx=3D_hbEvent("pv");hbx.vpc=3D"HBX0100u";hbx.gn=3D"ehg-oreilly.hitbox.co=
m";=0A=
=0A=
    hbx.acct=3D"DM551215AFSV;DM520404M4ZR"; //ACCOUNT NUMBER(S)=0A=
    hbx.pn=3D"PUT+PAGE+NAME+HERE"; //PAGE NAME(S)=0A=
    hbx.mlc=3D"CONTENT+CATEGORY"; //MULTI-LEVEL CONTENT CATEGORY=0A=
    hbx.pndef=3D"title"; //DEFAULT PAGE NAME=0A=
    hbx.ctdef=3D"full"; //DEFAULT CONTENT CATEGORY=0A=
=0A=
    hbx.lt=3D"auto"; //LINK TRACKING =0A=
    hbx.dlf=3D"n"; //DOWNLOAD FILTER=0A=
    hbx.dft=3D"n"; //DOWNLOAD FILE NAMING=0A=
    hbx.elf=3D"n"; //EXIT LINK FILTER=0A=
=0A=
    //SEGMENTS AND FUNNELS=0A=
    hbx.seg=3D""; //VISITOR SEGMENTATION=0A=
    hbx.fnl=3D""; //FUNNELS=0A=
=0A=
    //CAMPAIGNS=0A=
    hbx.cmp=3D""; //CAMPAIGN ID=0A=
    hbx.cmpn=3D"CMP"; //CAMPAIGN ID IN QUERY=0A=
    hbx.hra=3D""; //RESPONSE ATTRIBUTE=0A=
    hbx.hqsr=3D""; //RESPONSE ATTRIBUTE IN REFERRAL QUERY=0A=
    hbx.hqsp=3D""; //RESPONSE ATTRIBUTE IN QUERY=0A=
    hbx.hlt=3D""; //LEAD TRACKING=0A=
    hbx.hla=3D""; //LEAD ATTRIBUTE=0A=
    hbx.gp=3D""; //CAMPAIGN GOAL=0A=
    hbx.gpn=3D""; //CAMPAIGN GOAL IN QUERY=0A=
    hbx.hcn=3D""; //CONVERSION ATTRIBUTE=0A=
    hbx.hcv=3D""; //CONVERSION VALUE=0A=
    hbx.cp=3D"null"; //LEGACY CAMPAIGN=0A=
    hbx.cpd=3D""; //CAMPAIGN DOMAIN=0A=
=0A=
    //CUSTOM VARIABLES=0A=
    hbx.ci=3D"";//CUSTOMER ID=0A=
    hbx.hc1=3D"";//CUSTOM 1=0A=
    hbx.hc2=3D"";//CUSTOM 2=0A=
    hbx.hc3=3D"";//CUSTOM 3=0A=
    hbx.hc4=3D"";//CUSTOM 4 =0A=
    hbx.pec=3D"";//ERROR CODES=0A=
    </SCRIPT>

<SCRIPT language=3Djavascript1.1 =
src=3D"http://www.oreillynet.com/hbx.js" defer=20
type=3Dtext/javascript></SCRIPT>
<!--//--><!-- END WEBSIDESTORY CODE  --><!-- hitbox --></BODY></HTML>

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://www.oreillynet.com/ruby/blog/images/logo.gif

[encoded data, 6916 characters]
LQ1RHSKEC5esI4Z95+cdAgA7

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://www.oreillynet.com/images/tabs/orn_black.gif

R0lGODlhcQAQAMQAAP////7+//3+/v39/vv8/d7r69vp6tfm59fl58rc4FaLnEeBkzN2hyRtfgdi
awNkaQZjawRjaQFlZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAQU
AP8ALAAAAABxABAAAAXPICAChTKdaKqubOu+cCy7DiII43g8c+//wCAKUiAQcgWJcMlsAhuFgXSQ
iPxEQCzWyT1tWwvDSOnKAVDaXPmcjp3R6+a3xRi9vtt3/h2ft/BxTH4sdoETfntehW1th3yKepB6
ZmyVkoqOiYSDKXiPmZqMlppwWo6Yp6eimJSWf5xofIiulKq0hZ2QoKGjt6mgd7Cov6iNsbaXKrKu
ncvFk7/GK7iv1MNpdqvDuXC7sb7JntvNn10+wuZc1uky6Oxy7u/y89Px9Pfy6/j79CIhADs=

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://www.oreillynet.com/images/tabs/ora_gray.gif

R0lGODlhUgAQAMQAAP7+//39/vv8/aS2vK26vqa3vMrZ3LS/wdXh49Xi49nl5tzn58TIyMfKysbJ
yf3+/srLy////8zMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA
UgAQAAAFomAQAcsgnWiqrmzrvnDKIA8Q3XfSxHzv/yfHQvDALSDApHJ5WIgiht1ySo0VFDdkdTWZ
SLpbJeEWRoHP3jKQrDZ7wW0fu9WFo7/10/2O5+bxdnVvcC1zfnqDgml7g32ObimBjpKFES6ShIqN
fIKHkH2UhCuGKphpj4igi3+qkauTr5UvnaiKrZmnsIGhsSykcaW5wCq/w6jGKcXIy6OWzM+VIQA7

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://www.oreillynet.com/images/tabs/safari_gray.gif

R0lGODlhcgAQAMQAAP7+//39/vv8/aS2vK26vqa3vMrZ3LS/wdXh49Xi49nl5tzn58TIyMfKysbJ
yf3+/srLy////8zMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA
cgAQAAAF1mAQAcsgnWiqrmzrvnAswwzyAFGeJ83s/8CgUOVYCB66BWTIbDqHh4UoYug9r9isqqDI
LZuTsFYmfpVh5/CERciZzyw4ep1Sy+f4WPmecrf2Lnw+e3RkhX+HgXSCJ35xiXYndmuREmKXkIua
aWqSmp6YnSiVoYKOj4mWnyqllJmihKqesrGjq7G1LaeIoLmTsrasn7jDoqqdtZOusy67dbPJt8vB
dcXQ1nKYzNmruhFvhb/Ax9rUtsaV5Nuu0efljBLOY/P0P/L1+Pkr9/r9+Pz+AmrJEQIAOw==

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://www.oreillynet.com/images/tabs/conf_gray.gif

R0lGODlhWAAQAMQAAP7+//39/vv8/aS2vK26vqa3vMrZ3LS/wdXh49Xi49nl5tzn58TIyMfKysbJ
yf3+/srLy////8zMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA
WAAQAAAFqWAQAcsgnWiqrmzrvvDLIA8Q3XfSxHzv/y3HQvDALSDApHK5OixEEcOOSa36Coob0qqa
eLlgwu3lnQC/4PS4hTb70GnumgU/ld13/F2y55u/fXkogWWDhSxzK3Vtf3p2jn5+gpGMkYaPli6J
XW6YlJCMe3B5jZiLgpMrmyltloCgkJeesq+snZwtq7adhJ6joreosKGvdSq6cclUyMrNQMzO0THQ
0tWIESEAOw==

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://www.oreillynet.com/images/ads/ad-tag-vertical.gif

R0lGODlhCwBaAIAAAJmZmf///yH5BAEHAAEALAAAAAALAFoAAAJujI8Jiev8lgpPgcuy3ldO4x1e
CIpQh22qmkJa+67wSoNzWTXUPuVuDaR0ZKxi5hakkWxDXenDSxqjIhR1KeU8e1Rcd+czZWtN7jLi
CjvHr3JMa0Gujyc5m0lXo83wex079/PW4OZH90cyIggoVQAAOw==

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://www.oreillynet.com/images/icon_listen_small.gif

R0lGODlhCgAJAPcAAP///5mZmdbW1rS0tKenp8/Pz+Tk5MLCwq2trfHx8aCgoOvr629vb2ZmZvj4
+O7u7snJyZ6ensvLy7u7u9LS0oWFhfX19eXl5fv7+/Dw8Ozs7MDAwNjY2Kampqurq8jIyKqqqq6u
rp2dnYaGho+Pj5GRkQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAKAAkA
AAhIAAEIHCjgQ4aBAikIfIDggUAMBBhoIGDhggcAFUo0YAAggoSOABqM2AigwwYACjCSIOkRgIiH
ESdWBIFQIYAHIRwiBMBBwsGAADs=

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://s5.addthis.com/button1-bm.gif

R0lGODlhfQAQAIcAAAAAAA0NDRAQEBMTExwcHB8fHzIPRABrJx1nLzZ/RUJ8JAAAkwA5oAANywAA
/x0g/x8h/zI0/zlcmDVHrhxZzlJ8s2ZttCGZACyzL1e8AFO7PGCtMkaoR0qgcXHNSF2Vy1Sc2GSa
1W7DjELG/7prAIddTrV0RP8AAP8ABOkfIv4AJv8zINg/TO53EP9nAOR3N/dkJf9pOv5tTP9zR/91
SP91Sf97Uf98U/99VNcY/rybFKyPKKeDfZbeLZ3bR8aQJtKmANi8ANy4APaPAfCJMf+qAPq3CcWO
S9apU/+GY/WxTtTGGPbNBPrRAPvDL/b2B/r6J8XFfvzMTouLi5CQkJGRkZaWlpeXl5mZmZqampub
m5ycnJeiqKSZt760m6GhoaOjo6ampqenp6qqqq6urquiuLCwsLGxsbW1tba2tre3t7i4uL6+vru7
xru8yr+/yZ3W/6TY4bfr/O6WgNbNuNvsvMDAwMHBwcLCwsPDw8XFxcbGxsfHx8HBzMTEz8rKyszM
zM3Nzc7OzsXF0cbG0cjI08vL18nN28zM2c3N2M/P29DQ0NLS0tbT1tXV1dnZ2dra2tvb29zc3N3d
3d/f39TF5dXZ5NXf6eDN7P/e6Pzf8P/j1ePj4+Tk5Obm5ujo6Orq6uzs7O3t7e7u7u/v7+3z8+/2
9vzk5fDw8PHx8fHz8/Pz8/T09PX19vb29vf39/b3+ff0/Pf6+vj4+Pr6+vv7+/r6///7//z8/Pz/
//3//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAMAADkALAAAAAB9ABAA
AAj/AHPksEOwoMGDCBMqXMiwocOHECPaETgQ0q6LGDNq3Mixo8ePIEOKHDkS0kQ7FkmqXMmyZcZc
ulx6NGkHY5KbOG/K3NmylU+fD4IG9ehojNE/HE8pIZIi00iCF5PcmEp1ahKeWEf+BBrUwQONatas
2RUIY56NtuY4gYGihIhddTbA8gh1l9QbNS7WsJoRgF8AGP8G9nsRcOFdhgMXJoxYMGLFHLe2ehBB
aMYwF2uF+bILFSUtaTRqclHkhIoOHHxkUFCJbk27eGNcjLH3KuTHiQHnfsybcWPeuBUbTrxR8gMI
ljFi2VWLE5ZJkfbksWPlVsZNLY6sYHHAQ48LZax3/6wrdeMN24cP714PXHdw9uqBR976wIH9rxin
7AIF6corPXvs0clyGR0CxwgUeJEABhoggMlHBOGCS3kanSehhH8BgOGFGmq4oV8X4uLhiCJmWCKI
JYaoIoYZJoKIIokQIuEstexyBRVisLEIKqmIcgYZKoYgBwgNmCBFFEv8EMuKIRJECy1S4UDDRTTg
cN6TTwKApZZaZklLl1+GCSaYXo4p5pZhYqlmlgP8Zcibhvjx5Cy0zDILFnYCMgoqkpBBJ5aXfBAH
AxO8YAQUTSAhy5prEuSKK1LZMMNFM9hw3qOPAoCppppm6kqnn4YqKqiegsqpp6NiqmqmBBTgVyGw
Ft3Sh6qs3AHGHawIEsoak5jBCqamVCABFwsYMAQTTwDRxarMErTKKndVZdWzz2ZI7V/X+lXttasA
QO223oLLbbjdfvstAAEI4Ncg7A7yhrl87GLHKo90gocnaHxbCrWq8ECCEEHoYIG5BBNEysEyJKxw
wgc37PDDEEcs8cQUS5whAG1knLHDoVCxBRWhVKFFFlqAPDEdO7jRiCUNA0CKyy4fTBAjodRs8804
56zzzjz37PPPQActdCiMnLTIJ0gnrfTSTDft9NNQRy311FRTvchEAkmk9dZcd+01QwIFBAA7

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://www.oreillynet.com/images/ads/advertisement.gif

R0lGODlheAAKAIAAAGZmZv///yH5BAEAAAEALAAAAAB4AAoAQAJtjI+py+0Po5zUgHMtRiBr5W0c
44ViVi6pWLWfO8LyY872jef5Gqw8z3r1VCzU6xes6ZbMppOEMymfUF1HehWWOhyuxSvsZTFg8aVs
7pbHUTZy+HWDEtjQFWyEm/HJ5V1tVwf0FRMneKIll8hQAAA7

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://creativecommons.org/images/public/somerights.gif

R0lGODlhWAAfAMQAAGl6afT29HOEc+rs6n6Nft/j356qnr/Gv7S9tE5fTsnQyZSglG6CbqmzqdTZ
1EdVR4mXif///wAAAF5xXgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAA
AAAALAAAAABYAB8AAAX/oCSOZGmeaKqubOu+cCybUR1J9p3beC3muJ7vFuQBhbqhUTn8CZ/OEVEX
pUqd1qqWNA1Gv93w1QsUk6G8Yg9ZTbuZybjW+MXaz8Q5fjs2c717altldHg+e2WDblhwT2GHS3kz
k5SVlpeYlDubnJ2en6ChopwME6anqKmqq6ytrq+wrAmlsbW2rg0Nt7azu76xEDWmwr+vva4CuQ0G
AqsCBg0EEwAQBADSANDSps8NEKbBEeAQAuTjAAAL3r/HqwQONQUDNQ7NpwY5CMEBAQ4EATYOTAhX
IEKBBTnC4XMwgUCEAALm0fPVLhWEAAMMnMo2IMA2ATW8FThA0MA8CADg/xFo4GDBBHjqaqCsAUBY
gwgHFERoAOBABI23Kp76dwCAKgAFPE5YiCpYgYYRBuSCp2ulA4AQwg0TpxNC15ANfDIMSitVgQJG
VwEYwPDmWHARGO5zQNdBAwRRD5zUOkEYvgYY+8ati2CX0AkIvzW0V84UQgIIB4wLxhBkAKMra0Yw
WjArMWE15xUG2KynPV5lTyGQjLQjAnzymgXQVZAtRoRjdRZAAHABwAM+I8yM61DcBJ0RpN2UOk8X
WVV0l24WICBA4W0OBPYEqEDAu8LTVsd1CaGgAgQtJwBOHh2xAwWnGswrAPR5qug3T+1E9d4UNXPc
ZGVPVv8ZJeBAKBGI4P9pWSlWYFanlIPSKocdUFkACigAXAGANSPVUgCFNAFeNuhSQ4hnnQiSQfEU
9JB3LkZFQDghtpWDc6gchk8zK/EEQC7fgLRAdTuV5wBsC/gmXA0HKKmAkjdFgICTUMJD0nLh5FID
SANkdcA2OabmH4auKBCAdE9N89JPptxE4jfwwLkTTWvKSeIpzX0WwYocKpbKYeqxuQo+LrnFn3Bt
RoCcnHJGaUqca8Jj3JqOCraURFKqAugEPiGQln86gReZKTP65JypMtVJKTGQUkUnAADhY5ww32RD
TJitrGcXSw/VN0FBu/ETTk4vptrqnMYde1dU8inKl0zMiqWpmKkkU5c9XZ+CWoMC0pS3rTR0SYOe
uEe2N+6IR6o3z2zXtBedAS4WNW0x9NZrbwIJPKDvvvz26++/AAcs8MAEA5xACAA7

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: text/css;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.oreillynet.com/blogs/style.css

BODY {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; FONT: 75% Verdana, Arial, Helvetica, sans-serif; PADDING-TOP: 0px
}
H1 {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; FONT: 75% Verdana, Arial, Helvetica, sans-serif; PADDING-TOP: 0px
}
FORM {
	MARGIN: 0px
}
BLOCKQUOTE {
	CLEAR: both; PADDING-RIGHT: 10px; PADDING-LEFT: 10px; BACKGROUND: =
#efefef; PADDING-BOTTOM: 10px; PADDING-TOP: 10px
}
BLOCKQUOTE + BLOCKQUOTE {
	MARGIN: 0px
}
PRE {
	CLEAR: both; PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-SIZE: 12px; =
PADDING-BOTTOM: 2px! important; OVERFLOW: auto; WIDTH: auto! important; =
PADDING-TOP: 2px; BACKGROUND-COLOR: #efefef
}
CODE {
	COLOR: #003366; FONT-FAMILY: 'Andale Mono','Courier New', Courier, =
monospace
}
A IMG {
	BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: =
none; BORDER-BOTTOM-STYLE: none
}
#blog TABLE {
	MARGIN: 1em 0px 0px 1px; BORDER-COLLAPSE: collapse; empty-cells: show
}
#article TABLE {
	MARGIN: 1em 0px 0px 1px; BORDER-COLLAPSE: collapse; empty-cells: show
}
TD {
	BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: black =
1px solid; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; BORDER-LEFT: black =
1px solid; PADDING-TOP: 2px; BORDER-BOTTOM: black 1px solid
}
TH {
	BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: black =
1px solid; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; BORDER-LEFT: black =
1px solid; PADDING-TOP: 2px; BORDER-BOTTOM: black 1px solid
}
#featurebar TABLE {
	MARGIN: 0px
}
#featurebar TD {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; BORDER-TOP-STYLE: none; PADDING-TOP: 0px; BORDER-RIGHT-STYLE: none; =
BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none
}
TH {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; BORDER-TOP-STYLE: none; PADDING-TOP: 0px; BORDER-RIGHT-STYLE: none; =
BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none
}
TH {
	BACKGROUND-COLOR: #efefef; TEXT-ALIGN: left
}
THEAD TH {
	TEXT-ALIGN: center
}
CAPTION {
	FONT-STYLE: italic; TEXT-ALIGN: left; caption-side: top
}
H1 {
	FONT-WEIGHT: bold; FONT-SIZE: 17px; MARGIN: 0px; FONT-FAMILY: Verdana, =
Arial, Helvetica, sans-serif
}
H2 {
	FONT-WEIGHT: bold; FONT-SIZE: 17px; MARGIN: 0px; FONT-FAMILY: Verdana, =
Arial, Helvetica, sans-serif
}
H2 A {
	COLOR: black; TEXT-DECORATION: none
}
H2 A:hover {
	TEXT-DECORATION: underline
}
H3 {
	FONT-WEIGHT: bold; FONT-SIZE: 14px; MARGIN-BOTTOM: 0px; FONT-FAMILY: =
Verdana, Arial, Helvetica, sans-serif
}
H4 {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; MARGIN-BOTTOM: 0px; FONT-FAMILY: =
Verdana, Arial, Helvetica, sans-serif
}
H5 {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; MARGIN-BOTTOM: 0px; FONT-FAMILY: =
Verdana, Arial, Helvetica, sans-serif
}
H6 {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; MARGIN-BOTTOM: 0px; FONT-FAMILY: =
Verdana, Arial, Helvetica, sans-serif
}
H3 + P {
	MARGIN-TOP: 0px
}
H4 + P {
	MARGIN-TOP: 0px
}
H5 + P {
	MARGIN-TOP: 0px
}
H6 + P {
	MARGIN-TOP: 0px
}
#header {
	MIN-WIDTH: 970px; POSITION: relative
}
#page-content {
	BACKGROUND: url(http://www.oreillynet.com/blogs/images/background.gif) =
repeat-y; WIDTH: 970px
}
#content {
	BACKGROUND: url(http://www.oreillynet.com/blogs/images/background.gif) =
repeat-y; WIDTH: 970px
}
#footer {
	CLEAR: both; BORDER-TOP: #ccc 2px solid; Z-INDEX: 1; PADDING-BOTTOM: =
10px; FONT: 10px verdana; BACKGROUND-COLOR: #efefef
}
OL#menubar {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BACKGROUND: #000; FLOAT: left; =
PADDING-BOTTOM: 0px; MARGIN: 1px; WIDTH: 100%; PADDING-TOP: 0px
}
OL#menubar LI {
	BORDER-RIGHT: #fff 1px solid; DISPLAY: inline; FLOAT: left; MARGIN: =
0px; FONT: bold 11px verdana,helvetica,sans-serif; LIST-STYLE-TYPE: none
}
OL#menubar LI A {
	PADDING-RIGHT: 8px; DISPLAY: block; PADDING-LEFT: 8px; PADDING-BOTTOM: =
5px; COLOR: #fff; PADDING-TOP: 5px; TEXT-DECORATION: none
}
OL#menubar LI:hover {
	COLOR: #fff
}
#tabs {
	OVERFLOW: hidden; HEIGHT: 16px
}
#tabs OL {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; PADDING-TOP: 0px
}
#tabs OL LI {
	DISPLAY: inline; FLOAT: left; MARGIN: 0px; LIST-STYLE-TYPE: none
}
#tabs IMG {
	BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: =
0px; BORDER-RIGHT-WIDTH: 0px
}
#account-links {
	MARGIN-TOP: 2px; FLOAT: right; FONT: 10px verdana; MARGIN-RIGHT: 12px
}
#leaderboard {
	PADDING-RIGHT: 0px; MIN-WIDTH: 790px; PADDING-LEFT: 0px; BACKGROUND: =
#efefef; PADDING-BOTTOM: 10px; PADDING-TOP: 10px; HEIGHT: 90px; =
TEXT-ALIGN: center
}
#leaderboard * {
	BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: =
0px; BORDER-RIGHT-WIDTH: 0px
}
#textbar {
	FONT: 10px Verdana, Arial, Helvetica, sans-serif; COLOR: white; =
PADDING-TOP: 6px; HEIGHT: 18px; BACKGROUND-COLOR: #69c; TEXT-ALIGN: =
center
}
#textbar A {
	FONT: 10px Verdana, Arial, Helvetica, sans-serif; COLOR: white; =
PADDING-TOP: 6px; HEIGHT: 18px; BACKGROUND-COLOR: #69c; TEXT-ALIGN: =
center
}
.left {
	FLOAT: left; MARGIN: 0px 1em 1em 0px
}
.right {
	FLOAT: right; MARGIN: 0px 0px 1em 1em
}
.center {
	CLEAR: both; DISPLAY: block; MARGIN: 0px auto 1em
}
.image {
	MARGIN-TOP: 1em
}
.image P {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; PADDING-TOP: 0px; FONT-STYLE: italic
}
#article TABLE.adtag {
	MARGIN: 0px
}
#article TABLE#page-break TD {
	BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: =
none; BORDER-BOTTOM-STYLE: none
}
#article TABLE.adtag TD {
	BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: =
none; BORDER-BOTTOM-STYLE: none
}
#article TABLE#article-tools TD {
	BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: =
none; BORDER-BOTTOM-STYLE: none
}
#blog H2.archive {
	MARGIN-BOTTOM: 1em; BORDER-BOTTOM: #ccc 2px solid
}
#sidebar H2 {
	FONT-SIZE: 110%; MARGIN: 1em 0px 0px
}
#blog {
	PADDING-RIGHT: 5px; MARGIN-TOP: 1em; DISPLAY: inline; FLOAT: left; =
PADDING-BOTTOM: 10px; MARGIN-LEFT: 10px; WIDTH: 590px; MARGIN-RIGHT: 5px
}
#article {
	PADDING-RIGHT: 5px; MARGIN-TOP: 1em; DISPLAY: inline; FLOAT: left; =
PADDING-BOTTOM: 10px; MARGIN-LEFT: 10px; WIDTH: 590px; MARGIN-RIGHT: 5px
}
#sidebar {
	PADDING-LEFT: 10px; FLOAT: left; WIDTH: 170px
}
.sidebar-item {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; MARGIN-BOTTOM: 20px; =
PADDING-BOTTOM: 0px; PADDING-TOP: 0px
}
.sidebar-item H3 {
	BORDER-RIGHT: #999 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #999 1px =
solid; PADDING-LEFT: 5px; FONT-SIZE: 11px! important; BACKGROUND: =
url(/images/box-item-header.gif) no-repeat 0px 0px; PADDING-BOTTOM: 5px; =
MARGIN: 0px; BORDER-LEFT: #999 1px solid; PADDING-TOP: 5px; POSITION: =
relative; TEXT-ALIGN: center
}
.sidebar-item-content {
	BORDER-RIGHT: #999 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #999 1px =
solid; PADDING-LEFT: 10px; FONT-SIZE: 95%; PADDING-BOTTOM: 10px; MARGIN: =
0px; BORDER-LEFT: #999 1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: #999 =
1px solid; POSITION: relative
}
#skyscraper {
	FLOAT: left; MARGIN-LEFT: 10px; WIDTH: 170px; PADDING-TOP: 1em
}
.ad-header {
	FONT-SIZE: 0.9em; TEXT-ALIGN: center
}
#blog .post {
	MARGIN-BOTTOM: 15px; PADDING-BOTTOM: 15px; OVERFLOW: hidden; =
BORDER-BOTTOM: #ccc 2px solid
}
.post-content {
	CLEAR: left
}
.post-content-footer {
	CLEAR: both
}
.post-byline {
	FONT-SIZE: 90%; FONT-STYLE: italic
}
.post-footer {
	MARGIN-TOP: 10px; FONT-SIZE: 90%
}
#blog .post P {
	MARGIN-BOTTOM: 0px
}
#blog .post BLOCKQUOTE > P:first-child {
	MARGIN-TOP: 0px
}
#blog byline {
	FONT-SIZE: 100%
}
#sidebar UL {
	PADDING-LEFT: 1.5em; MARGIN: 0px
}
#sidebar UL LI {
	MARGIN-BOTTOM: 2px
}
#comments > .comment:first-child {
	BORDER-TOP-STYLE: none
}
.comment {
	PADDING-RIGHT: 10px; BORDER-TOP: #ccc 2px solid; PADDING-LEFT: 10px; =
PADDING-BOTTOM: 10px; OVERFLOW: hidden; PADDING-TOP: 0px
}
.comment-preview {
	BORDER-RIGHT: #ccc 2px solid; PADDING-RIGHT: 5px; BORDER-TOP: #ccc 2px =
solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; OVERFLOW: auto; =
BORDER-LEFT: #ccc 2px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #ccc 2px =
solid; HEIGHT: 100px
}
#comment-form {
	BORDER-RIGHT: #ccc 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #ccc 1px =
solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; BORDER-LEFT: #ccc 1px =
solid; MARGIN-RIGHT: 5px; PADDING-TOP: 10px; BORDER-BOTTOM: #ccc 1px =
solid; BACKGROUND-COLOR: #efefef
}
.rbox {
	MARGIN-TOP: 2em; COLOR: #000; LINE-HEIGHT: 14px; PADDING-TOP: 0px; =
BACKGROUND-COLOR: #ccc
}
.rbcontent {
	MARGIN: 0px 6px; COLOR: #000; BACKGROUND-COLOR: #ccc
}
.rboxtop {
	BACKGROUND: url(http://www.oreillynet.com/images/gray_tr.gif) no-repeat =
right top
}
.rboxtop DIV {
	BACKGROUND: url(http://www.oreillynet.com/images/gray_tl.gif) no-repeat =
left top
}
.rboxbot {
	BACKGROUND: url(http://www.oreillynet.com/images/gray_br.gif) no-repeat =
right top
}
.rboxbot DIV {
	BACKGROUND: url(http://www.oreillynet.com/images/gray_bl.gif) no-repeat =
left top
}
.rboxtop {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 1px; PADDING-BOTTOM: =
0px; MARGIN: 0px; PADDING-TOP: 0px; HEIGHT: 6px
}
.rboxtop DIV {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 1px; PADDING-BOTTOM: =
0px; MARGIN: 0px; PADDING-TOP: 0px; HEIGHT: 6px
}
.rboxbot {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 1px; PADDING-BOTTOM: =
0px; MARGIN: 0px; PADDING-TOP: 0px; HEIGHT: 6px
}
.rboxbot DIV {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 1px; PADDING-BOTTOM: =
0px; MARGIN: 0px; PADDING-TOP: 0px; HEIGHT: 6px
}
.tb_left {
	MARGIN-TOP: 0.5em; FLOAT: left; WIDTH: 30%; HEIGHT: 20px
}
.tb_right {
	MARGIN-TOP: 0.5em; FLOAT: right; WIDTH: 60%; HEIGHT: 20px; TEXT-ALIGN: =
right
}
.trb_left {
	MARGIN-TOP: 0.5em; FLOAT: left; WIDTH: 60%; HEIGHT: 20px
}
.trb_right {
	MARGIN-TOP: 0.5em; FLOAT: right; WIDTH: 30%; HEIGHT: 20px; TEXT-ALIGN: =
right
}
DIV.feedback {
	MARGIN-TOP: 1em
}
.feedback UL {
	PADDING-RIGHT: 0px; PADDING-LEFT: 1em; PADDING-BOTTOM: 0px; MARGIN: 0px =
0px 0px 1em; PADDING-TOP: 0px
}
.feedback LI {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; LIST-STYLE-IMAGE: =
url(http://www.oreillynet.com/images/bullet-post.gif); PADDING-BOTTOM: =
1em; MARGIN-LEFT: 0px; PADDING-TOP: 0px
}
.feedback UL UL LI {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; LIST-STYLE-IMAGE: =
url(http://www.oreillynet.com/images/bullet-reply.gif); PADDING-BOTTOM: =
1em; MARGIN-LEFT: 0px; PADDING-TOP: 0px
}
LI.trackback {
	PADDING-RIGHT: 0px; PADDING-LEFT: 2em; LIST-STYLE-IMAGE: =
url(http://www.oreillynet.com/images/icons/trackback_18.gif); =
PADDING-BOTTOM: 1em; PADDING-TOP: 0px
}
.headline {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; FONT-FAMILY: Verdana, Arial, =
Helvetica, sans-serif
}

@media Print   =20
{
#blog .post {
	OVERFLOW: visible
}
    }
.listen {
	PADDING-RIGHT: 0px; DISPLAY: block; PADDING-LEFT: 10px; FONT-SIZE: =
0.75em; FLOAT: right; PADDING-BOTTOM: 0px; MARGIN: 0.5em 0px 0px 10px; =
LINE-HEIGHT: 1.5em; PADDING-TOP: 0px; LIST-STYLE-TYPE: none; HEIGHT: =
1.8em; TEXT-ALIGN: right
}
.listen LI {
	PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: =
5px; MARGIN: 0px; PADDING-TOP: 5px; TEXT-ALIGN: right
}
.listen A {
	PADDING-RIGHT: 14px; DISPLAY: block; PADDING-LEFT: 0px; FLOAT: left; =
PADDING-BOTTOM: 0px; PADDING-TOP: 0px; HEIGHT: 1.8em
}
.listen .button {
	FONT-SIZE: 12px; MARGIN-LEFT: 10px
}
.listen .option {
	DISPLAY: none; FONT-SIZE: 12px
}

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: text/css;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Location: http://www.oreillynet.com/ruby/blog/style.css

#textbar {
	BACKGROUND-COLOR: #900
}
UL#menubar LI:hover {
	BACKGROUND-COLOR: #900
}
#page-content {
	BACKGROUND-IMAGE: none; WIDTH: 998px
}
#content {
	BACKGROUND-IMAGE: none; WIDTH: 998px
}
#sidebar {
	WIDTH: 198px
}

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: application/x-js
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.oreillynet.com/engine.js

// JavaScript Document=0A=
/* <![CDATA[ */=0A=
function getCookie(name) {=0A=
  var dc =3D document.cookie;=0A=
  var prefix =3D name + "=3D";=0A=
  var begin =3D dc.indexOf("; " + prefix);=0A=
  if (begin =3D=3D -1) {=0A=
    begin =3D dc.indexOf(prefix);=0A=
    if (begin !=3D 0) return null;=0A=
  } else=0A=
    begin +=3D 2;=0A=
  var end =3D document.cookie.indexOf(";", begin);=0A=
  if (end =3D=3D -1)=0A=
    end =3D dc.length;=0A=
  return unescape(dc.substring(begin + prefix.length, end));=0A=
}=0A=
=0A=
// list all show/hide element IDs here=0A=
menus_array =3D new Array =
('business','databases','design','audiovideo','photography','hardware','h=
omeoffice','microsoft','sysadmin','os','programming','science','security'=
,'softwareengineering','web','partnertopics','companies','showcases','ful=
ldesc','reviews');=0A=
menus_status_array =3D new Array ();// remember switches=0A=
img_close =3D 'rollup';=0A=
img_open =3D 'rolldown';=0A=
=0A=
function toggleSheet(theid) {=0A=
  if (document.getElementById) {=0A=
    var switch_id =3D document.getElementById(theid);=0A=
    var imgid =3D theid+'Button';=0A=
    var button_id =3D document.getElementById(imgid);=0A=
    if (menus_status_array[theid] !=3D 'show') {=0A=
      button_id.className =3D 'rolldown';=0A=
      switch_id.className =3D 'showSwitch';=0A=
	  menus_status_array[theid] =3D 'show';=0A=
	  document.cookie =3D theid+'=3Dshow';=0A=
    } else {=0A=
      button_id.className =3D 'rollup';=0A=
      switch_id.className =3D 'hideSwitch';=0A=
	  menus_status_array[theid] =3D 'hide';=0A=
	  document.cookie =3D theid+'=3Dhide';=0A=
    }=0A=
  }=0A=
}=0A=
=0A=
function setMenu() { // read cookies and set menus to last visited state=0A=
  if (document.getElementById) {=0A=
    for (var i=3D0; i < menus_array.length; i++) {=0A=
      var idname =3D menus_array[i];=0A=
      if (document.getElementById(idname)) {=0A=
		var switch_id =3D document.getElementById(idname);=0A=
		var imgid =3D idname+'Button';=0A=
		var button_id =3D document.getElementById(imgid);=0A=
		// alert(imgid);=0A=
		if (getCookie(idname) =3D=3D 'show') {=0A=
		  button_id.className =3D 'rolldown';=0A=
		  switch_id.className =3D 'showSwitch';=0A=
		  menus_status_array [idname] =3D 'show';=0A=
		} else {=0A=
		  button_id.className =3D 'rollup';=0A=
		  switch_id.className =3D 'hideSwitch';=0A=
		  menus_status_array [idname] =3D 'hide';=0A=
		}=0A=
	  } // else { alert("Switch '"+idname+"' is not present on this =
page."); }=0A=
    }=0A=
  }=0A=
}=0A=
/* ]]> */=0A=

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: application/x-js
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.oreillynet.com/common.js

// common js code for network=0A=
//Clear inherited frames=0A=
=0A=
if (parent !=3D self) {=0A=
                top.location=3Dself.document.location;=0A=
}=0A=
=0A=
//random number for dc=0A=
var ord =3D (ord !=3D null ? ord : Math.random()*10000000000000000 );=0A=
=0A=
//var ord =3D Math.round(Math.random() * 10000000000);=0A=
//var abc =3D Math.random() + "";=0A=
//var ord =3D abc.substring(2,abc.length);=0A=
=0A=
//get stylesheet regardless of browser=0A=
//document.write('<link rel=3D"STYLESHEET" type=3D"text/css" =
href=3D"http://oreillynet.com/styles/main.css">');=0A=
=0A=
//Shared Functions=0A=
=0A=
// Pop-Up Embedder Script by David Battino, www.batmosphere.com=0A=
function PlayerOpen(soundfiledesc,soundfilepath, width, height) {=0A=
   winPadding =3D 130;//for the header and caption=0A=
   if (!width){=0A=
      winWidth=3D320;=0A=
      width   =3D300;=0A=
   }=0A=
   else{=0A=
   winWidth   =3D winPadding  + Number(width);=0A=
   }=0A=
=0A=
   if(!height){=0A=
      winHeight=3D190;=0A=
      height =3D 42;=0A=
   }=0A=
   else{=0A=
      winHeight   =3D winPadding  + Number(height);                      =
        =0A=
   }=0A=
=0A=
=0A=
	PlayWin =3D window.open('','Player','width=3D' + winWidth + =
',height=3D' + winHeight + =
',top=3D0,left=3D0,resizable=3D0,scrollbars=3D0,titlebar=3D0,toolbar=3D0,=
menubar=3D0,status=3D0,directories=3D0');=0A=
=0A=
    PlayWin.focus();=0A=
=0A=
    PlayWin.document.write("<html><head><title>" + soundfiledesc + =
"</title>");=0A=
	PlayWin.document.write("<link rel=3D'STYLESHEET' type=3D'text/css' =
href=3D'http://www.oreillynet.com/styles/main.css' /></head>");=0A=
	PlayWin.document.write("<body bgcolor=3D'#ffffff'>");=0A=
    PlayWin.document.write("<b style =
=3D'font-size:18px;font-family:Verdana,sans-serif;line-height:1.5'>" + =
soundfiledesc + "</b>");=0A=
    PlayWin.document.write("<div align=3D'center'><object width=3D'" + =
width + "' height=3D'" + height + "' >");=0A=
    PlayWin.document.write("<param name=3D'SRC' value=3D'" +  =
soundfilepath + "'>");=0A=
    PlayWin.document.write("<param name=3D'AUTOPLAY' VALUE=3D'true'>");=0A=
    PlayWin.document.write("<param name=3D'CONTROLLER' VALUE=3D'true'>");=0A=
    PlayWin.document.write("<embed src =3D'" + soundfilepath + "' =
autostart=3D'true' loop=3D'false' width=3D'" + width + "' height=3D'" + =
height + "' controller=3D'true' bgcolor=3D'#ffffff' >");=0A=
    PlayWin.document.write("</embed></object></div>");=0A=
=0A=
    PlayWin.document.write("<p =
style=3D'font-size:12px;font-family:Verdana,sans-serif;text-align:center'=
><a href=3D'" + soundfilepath +"'>Download this file</a> <span =
style=3D'font-size:10px'>(right-click or Option-click)</span></p>");=0A=
	PlayWin.document.write("<form><div align=3D'center'><input =
type=3D'button' value=3D'Close this window' =
OnClick=3D'javascript:window.close();'></div></form>");=0A=
=0A=
    PlayWin.document.write("</body></html>");=0A=
=0A=
    PlayWin.document.close(); // "Finalizes" new window=0A=
}=0A=
=0A=
// Pop-Up Embedder by David Battino, www.batmosphere.com=0A=
function PopImage(filedesc,filepath,origwidth,origheight,caption) {=0A=
	winPadding =3D 100;//for the header and caption=0A=
	winWidth   =3D winPadding  + Number(origwidth);=0A=
   winHeight  =3D winPadding  + Number(origheight);=0A=
	=0A=
    PlayWin =3D window.open('','Image','width=3D' + winWidth + =
',height=3D' + winHeight + =
',resizable=3D1,scrollbars=3D1,titlebar=3D0,toolbar=3D0,menubar=3D0,statu=
s=3D0,directories=3D0');=0A=
	PlayWin.document.write("<html><head><title>" + filedesc + "</title>");=0A=
	PlayWin.document.write("<link rel=3D'STYLESHEET' type=3D'text/css' =
href=3D'http://www.oreillynet.com/styles/main.css' /></head>");=0A=
    PlayWin.document.write("<body bgcolor=3D'#ffffff'>");=0A=
    PlayWin.document.write("<div align=3D'center' >");=0A=
    PlayWin.document.write("<h3>" + filedesc + "</h3>");=0A=
    PlayWin.document.write("<div style=3D'width:" + origwidth + =
"px;text-align:left; '>");=0A=
    PlayWin.document.write("<img src=3D'" + filepath + "' id=3D'image1' =
name=3D'image1' alt=3D'" + filedesc + "' width=3D'" + origwidth + "' =
height=3D'" + origheight + "'title=3D'" +filedesc + "' />");=0A=
    PlayWin.document.write("<p class=3D'secondary'>" + caption + "</p>");=0A=
    PlayWin.document.write("</div>");=0A=
    PlayWin.document.write("<form><input type=3D'button' value=3D'Close =
this window' onclick=3D'javascript:window.close()'><br /><br />");=0A=
    PlayWin.document.write("</div>");=0A=
    PlayWin.document.write("</form>");=0A=
    PlayWin.document.write("</body></html>");=0A=
=0A=
    PlayWin.document.close(); // "Finalizes" new window=0A=
}=0A=
=0A=
// JavaScript Document=0A=
// Pop-Up Embedder Script by David Battino, www.batmosphere.com=0A=
// v 2005-05-02a=0A=
=0A=
function =
MediaPop(popuptitle,imgpath,imgwidth,imgheight,caption,soundpath,UniqueID=
) { // CONSIDER ADDING ERROR HANDLING=0A=
=0A=
     var winWidth =3D Number(imgwidth) + 100; // imgwidth should be =
<651; shoot for 600=0A=
     var rawHeight =3D Number(imgheight) + 168 + caption.length/7; // =
calculate window height based on caption length=0A=
     var winHeight =3D Math.round(rawHeight * =
Math.pow(10,0))/Math.pow(10,0); // round to integer=0A=
MediaWin =3D window.open('',UniqueID,'width=3D' + winWidth + =
',height=3D' + winHeight + =
',top=3D0,left=3D0,resizable=3D1,scrollbars=3D0,titlebar=3D0,toolbar=3D0,=
menubar=3D0,status=3D0,directories=3D0,personalbar=3D0');=0A=
     MediaWin.focus();=0A=
     var winContent =3D "<html><head><title>" + popuptitle + "</title>";=0A=
     winContent +=3D "<link rel=3D'STYLESHEET' type=3D'text/css' =
href=3D'http://www.oreillynet.com/styles/main.css' /></head>";=0A=
     winContent +=3D "<body style=3D'background-color:#fff; =
text-align:center;padding-top:1em;'>";=0A=
     =0A=
      winContent +=3D "<div align=3D'center'>";=0A=
      winContent +=3D "<div style=3D'width: " + imgwidth + "px; margin: =
0px; padding: 0px; text-align:left;'>"; // restrict width=0A=
     winContent +=3D "<img src=3D'" + imgpath + "' id=3D'image1' =
border=3D'0' alt=3D'" + popuptitle + "' width=3D'" + imgwidth + "' =
height=3D'" + imgheight + " 'title=3D'" + popuptitle + "' =
style=3D'border: 2px solid #000;'/>";=0A=
     winContent +=3D "<object width=3D'" + imgwidth + "' height=3D'42' =
>"; // add 4 to width to align controller with img border?=0A=
     winContent +=3D "<param name=3D'SRC' value=3D'" +  soundpath + "'>";=0A=
     winContent +=3D "<param name=3D'AUTOPLAY' VALUE=3D'true'>";=0A=
     winContent +=3D "<param name=3D'CONTROLLER' VALUE=3D'true'>";=0A=
     winContent +=3D "<param name=3D'BGCOLOR' VALUE=3D'#ffffff'>";=0A=
     winContent +=3D "<embed src =3D'" + soundpath + "' =
autostart=3D'true' loop=3D'false' width=3D'" + imgwidth + "' =
height=3D'42' controller=3D'true' bgcolor=3D'#ffffff'>";=0A=
     winContent +=3D "</embed></object>";=0A=
=0A=
         winContent +=3D "<p class=3D'secondary'>" + caption + "</p>";=0A=
         winContent +=3D "</div>";=0A=
=0A=
     winContent +=3D "<div style =3D 'font-size: 12px;font-family: =
Verdana,sans-serif'><a href =3D '" + soundpath +"'>Download audio =
file</a> <span style=3D'font-size:10px'>(right-click or =
Option-click)</span>";=0A=
    //winContent +=3D "<form><input type=3D'button' value=3D'Close this =
window' OnClick=3D'javascript:window.close();'></form>"; // Close button=0A=
     winContent +=3D " &#8226; <a href=3D'#' =
OnClick=3D'javascript:window.close();'>Close this window</a></p>";=0A=
=0A=
	=0A=
=0A=
     winContent +=3D "</div></div>";=0A=
      winContent +=3D "</body></html>";=0A=
     MediaWin.document.write(winContent); =0A=
     MediaWin.document.close(); // "Finalizes" new window=0A=
}=0A=
=0A=
//Atomz Search Code=0A=
=0A=
function searchverif() { =0A=
   if (document.searchForm.query.value.length < 1) {=0A=
       alert("Your search query is blank. Please enter a search term.");=0A=
       return false;=0A=
   } =0A=
   return true;=0A=
}=0A=
=0A=
function processQuery() {=0A=
=0A=
var d =3D document.searchForm;=0A=
var q =3D d.elements['query'].value;=0A=
q =3D q.replace(/&quot;/g, "%22");=0A=
=0A=
// set collection=0A=
d.elements['c'].value =3D d.elements['sp-q-1'].value; =0A=
// set sp-q=0A=
d.elements['sp-q'].value =3D d.elements['query'].value;=0A=
=0A=
var pat =3D /C\+\+/gi;=0A=
test =3D q.match(pat);=0A=
if (test !=3D null) {=0A=
   d.elements['sp-q'].value =3D d.elements['sp-q'].value.replace(pat, =
"CPLUSPLUS");=0A=
   }=0A=
=0A=
var pat =3D /C#/i;=0A=
test =3D q.match(pat);=0A=
if (test !=3D null) {=0A=
   d.elements['sp-q'].value =3D d.elements['sp-q'].value.replace(pat, =
"CNUM");=0A=
   }=0A=
=0A=
}=0A=
=0A=

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: application/x-js
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.oreillynet.com/blogs/mt-site.js

// Copyright (c) 1996-1997 Athenia Associates.=0A=
// http://www.webreference.com/js/=0A=
// License is granted if and only if this entire=0A=
// copyright notice is included. By Tomer Shiran.=0A=
=0A=
function setCookie (name, value, expires, path, domain, secure) {=0A=
    var curCookie =3D name + "=3D" + escape(value) + (expires ? "; =
expires=3D" + expires : "") +=0A=
        (path ? "; path=3D" + path : "") + (domain ? "; domain=3D" + =
domain : "") + (secure ? "secure" : "");=0A=
    document.cookie =3D curCookie;=0A=
}=0A=
=0A=
function getCookie (name) {=0A=
    var prefix =3D name + '=3D';=0A=
    var c =3D document.cookie;=0A=
    var nullstring =3D '';=0A=
    var cookieStartIndex =3D c.indexOf(prefix);=0A=
    if (cookieStartIndex =3D=3D -1)=0A=
        return nullstring;=0A=
    var cookieEndIndex =3D c.indexOf(";", cookieStartIndex + =
prefix.length);=0A=
    if (cookieEndIndex =3D=3D -1)=0A=
        cookieEndIndex =3D c.length;=0A=
    return unescape(c.substring(cookieStartIndex + prefix.length, =
cookieEndIndex));=0A=
}=0A=
=0A=
function deleteCookie (name, path, domain) {=0A=
    if (getCookie(name))=0A=
        document.cookie =3D name + "=3D" + ((path) ? "; path=3D" + path =
: "") +=0A=
            ((domain) ? "; domain=3D" + domain : "") + "; expires=3DThu, =
01-Jan-70 00:00:01 GMT";=0A=
}=0A=
=0A=
function fixDate (date) {=0A=
    var base =3D new Date(0);=0A=
    var skew =3D base.getTime();=0A=
    if (skew > 0)=0A=
        date.setTime(date.getTime() - skew);=0A=
}=0A=
=0A=
function rememberMe (f) {=0A=
    var now =3D new Date();=0A=
    fixDate(now);=0A=
    now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000);=0A=
    now =3D now.toGMTString();=0A=
    if (f.author !=3D undefined)=0A=
       setCookie('mtcmtauth', f.author.value, now, '/', '', '');=0A=
   // if (f.email !=3D undefined)=0A=
   //   setCookie('mtcmtmail', f.email.value, now, '/', '', '');=0A=
    if (f.url !=3D undefined)=0A=
       setCookie('mtcmthome', f.url.value, now, '/', '', '');=0A=
}=0A=
=0A=
function forgetMe (f) {=0A=
    //deleteCookie('mtcmtmail', '/', '');=0A=
    deleteCookie('mtcmthome', '/', '');=0A=
    deleteCookie('mtcmtauth', '/', '');=0A=
    //f.email.value =3D '';=0A=
    f.author.value =3D '';=0A=
    f.url.value =3D '';=0A=
}=0A=
=0A=
function hideDocumentElement(id) {=0A=
    var el =3D document.getElementById(id);=0A=
    if (el) el.style.display =3D 'none';=0A=
}=0A=
=0A=
function showDocumentElement(id) {=0A=
    var el =3D document.getElementById(id);=0A=
    if (el) el.style.display =3D 'block';=0A=
}=0A=
=0A=
var commenter_name;=0A=
=0A=
function individualArchivesOnLoad(commenter_name) {=0A=
	comment_form =3D document.getElementById("comment-form");=0A=
=0A=
	if (comment_form) {=0A=
        =0A=
		if (comment_form.email !=3D undefined &&  (mtcmtmail =3D =
getCookie("mtcmtmail")))=0A=
            comment_form.email.value =3D mtcmtmail;=0A=
=0A=
		if (comment_form.author !=3D undefined && (mtcmtauth =3D =
getCookie("mtcmtauth")))=0A=
	=0A=
            comment_form.author.value =3D mtcmtauth;=0A=
        =0A=
		if (comment_form.url !=3D undefined &&    (mtcmthome =3D =
getCookie("mtcmthome")))=0A=
            comment_form.url.value =3D mtcmthome;=0A=
=0A=
        if (mtcmtauth || mtcmthome) {=0A=
            comment_form.bakecookie.checked =3D true;=0A=
=0A=
        } else {=0A=
            comment_form.bakecookie.checked =3D false;=0A=
        }=0A=
    }=0A=
}=0A=
=0A=
//custom function to preview comments=0A=
function preview_comment(comment_text)=0A=
{=0A=
    // create popup preview window=0A=
    features =3D =
'menubar=3D0,toolbar=3D0,location=3D0,directories=3D0,scrollbars=3D0,stat=
us=3D0,resizable=3D0,width=3D625,height=3D200';=0A=
    popup =3D window.open('','commentpreview',features);=0A=
    if (popup.focus) popup.focus();=0A=
	=0A=
    // insert comment text into popup    =0A=
    popup.document.write("<html><head><title>Preview =
Comment</title><link rel=3D\"stylesheet\" type=3D\"text/css\" =
href=3D\"http://www.oreillynet.com/blogs/style.css\" /></head>");=0A=
    popup.document.write("<body>");=0A=
    popup.document.write("<div id=3D'blog'><h3>Comment Preview</h3><div =
class=3D'comments'><div class=3D'comment-preview'>" + =
wpautop(comment_text) + "</div></div></div><div =
style=3D'clear:both;text-align:center;'><button =
onclick=3D'window.close();'>Close</button></div>");=0A=
    popup.document.write("</body></html>");=0A=
    return true;=0A=
}=0A=
=0A=
// helper function for preview_comment=0A=
function wpautop(pee) {=0A=
	pee =3D pee + '\n\n';=0A=
	=0A=
	pee =3D pee.replace(/(<blockquote[^>]*>)/g, '\n$1');=0A=
	pee =3D pee.replace(/(<\/blockquote[^>]*>)/g, '$1\n');=0A=
		=0A=
	pee =3D pee.replace(/\r\n/g, '\n');=0A=
	pee =3D pee.replace(/\r/g, '\n');=0A=
	pee =3D pee.replace(/\n\n+/g, '\n\n');=0A=
	pee =3D pee.replace(/\n?(.+?)(?:\n\s*\n)/g, '<p>$1</p>');=0A=
	pee =3D pee.replace(/<p>\s*?<\/p>/g, '');=0A=
=0A=
	pee =3D pee.replace(/<p>\s*(<\/?blockquote[^>]*>)\s*<\/p>/g, '$1');=0A=
	pee =3D pee.replace(/<p><blockquote([^>]*)>/ig, '<blockquote$1><p>');=0A=
	pee =3D pee.replace(/<\/blockquote><\/p>/ig, '<p></blockquote>');	=0A=
	pee =3D pee.replace(/<p>\s*<blockquote([^>]*)>/ig, '<blockquote$1>');=0A=
	pee =3D pee.replace(/<\/blockquote>\s*<\/p>/ig, '</blockquote>');			=0A=
=0A=
   // ADDED TO STRIP OUT SCRIPT IN PREVIEW - eparker 20070823=0A=
   pee =3D pee.replace(/<\s*script([^>]*)>.*?<\s*\/\s*script([^>]*)>/ig, =
'');=0A=
   //pee =3D pee.replace(/<\s*script([^>]*)>/ig, '');=0A=
   //pee =3D pee.replace(/<\s*\/\s*script([^>]*)>/ig, '');=0A=
   =0A=
	pee =3D pee.replace(/\s*\n\s*/g, '<br />');=0A=
	return pee;=0A=
}=0A=

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: application/x-js
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.oreillynet.com/blogs/popup-media-player.js

// Pop-Up Embedder Script by David Battino, www.batmosphere.com
// With tweaks by Mark Levitt, http://digitalmedia.oreilly.com
// OK to use if this notice is included
  =20
var WindowNumber =3D 1;

function MakePlayer(filedesc,filepath,width,height)=20
{
    winPadding =3D 130; //for the header and caption

    if (!width)
    {
        winWidth =3D 320;
        width    =3D 300;
    }
    else
    {
        winWidth =3D winPadding + Number(width);
    }

    if(!height)
    {
        winHeight =3D 190;
        height    =3D 42;
    }
    else
    {
        winHeight =3D winPadding + Number(height);
    }

    PlayerWin =3D window.open('',WindowNumber,'width=3D' + winWidth + =
',height=3D' + winHeight + =
',top=3D0,left=3D0,resizable=3D0,scrollbars=3D0,titlebar=3D0,toolbar=3D0,=
menubar=3D0,status=3D0,directories=3D0');

    PlayerWin.focus();

    PlayerWin.document.write("<html><head><title>" + filedesc + =
"</title></head>");
    PlayerWin.document.write("<body bgcolor=3D'#9E9E9E' =
background=3D'http://www.oreillynet.com/blogs/popup-tile-vertical.jpg'>")=
; // verify image path
    PlayerWin.document.write("<div align=3D'center'>");
    PlayerWin.document.write("<b style =
=3D'font-size:18px;font-family:Verdana,sans-serif;line-height:1.5'>" + =
filedesc + "</b><br />");
    PlayerWin.document.write("<object width=3D'" + width + "' =
height=3D'" + height + "' >");
    PlayerWin.document.write("<param name=3D'SRC' value=3D'" +  filepath =
+ "'>");
    PlayerWin.document.write("<param name=3D'AUTOPLAY' =
VALUE=3D'true'>");
    PlayerWin.document.write("<param name=3D'CONTROLLER' =
VALUE=3D'true'>");
    PlayerWin.document.write("<embed src =3D'" + filepath + "' =
autostart=3D'true' loop=3D'false' width=3D'" + width + "' height=3D'" + =
height + "' controller=3D'true' bgcolor=3D'#9E9E9E'>");
    PlayerWin.document.write("</embed></object></div>");
    PlayerWin.document.write("<p =
style=3D'font-size:12px;font-family:Verdana,sans-serif;text-align:center'=
><a href=3D'" + filepath +"'>Download this file</a> <span =
style=3D'font-size:10px'>(right-click or Option-click)</span></p>");
    PlayerWin.document.write("<form><div align=3D'center'><input =
type=3D'button' value=3D'Close this window' =
onclick=3D'javascript:window.close();'></div></form>");
    PlayerWin.document.write("</body></html>");

    PlayerWin.document.close(); // "Finalizes" new window

    WindowNumber =3D WindowNumber + 1 // prevent subsequent clicks from =
using same window
}
------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://s5.addthis.com/js/widget.php?v=10

var  addthis_url   =3D '';=0A=
var  addthis_title =3D '';=0A=
=0A=
function addthis_click(obj, str){=0A=
=0A=
 var aturl  =3D 'http://www.addthis.com/bookmark.php';=0A=
 aturl +=3D '?v=3D10';=0A=
 aturl +=3D '&pub=3D'+addthis_pub;=0A=
 aturl +=3D '&url=3D'+encodeURIComponent(addthis_url);=0A=
 aturl +=3D '&title=3D'+encodeURIComponent(addthis_title);=0A=
=0A=
 =
window.open(aturl,'addthis','scrollbars=3Dyes,menubar=3Dno,width=3D620,he=
ight=3D520,resizable=3Dyes,toolbar=3Dno,location=3Dno,status=3Dno,screenX=
=3D200,screenY=3D100,left=3D200,top=3D100');=0A=
=0A=
=0A=
 return false;=0A=
}=0A=

------=_NextPart_000_0000_01C8587B.C3B54E40
Content-Type: application/x-js
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.oreillynet.com/hbx.js

//hbx.js,HBX1.3,COPYRIGHT 1997-2004 WEBSIDESTORY,INC. ALL RIGHTS =
RESERVED. U.S.PATENT No.6,393,479B1 & 6,766,370. =
INFO:http://websidestory.com/privacy=0A=
//changes here need to be made also to code for store.makezine.com; =
please notify webmaster@makezine.com of any updates=0A=
var _vjs=3D"HBX0132.01u";=0A=
var =
_dl=3D".exe,.zip,.wav,.wmv,.mp3,.mov,.mpg,.avi,.doc,.pdf,.xls,.ppt,.gz";=0A=
function _NA(a){return new Array(a?a:0)}function _NO(){return new =
Object()}=0A=
var =
_mn=3D_hbq=3D"",_hbA=3D_NA(),_hud=3D"undefined",_lv=3D_NO(),_ec=3D_if=3D_=
ll=3D_hec=3D_hfs=3D_hfc=3D_fvf=3D_ic=3D_pC=3D_fc=3D_pv=3D0,_hbi=3Dnew =
Image(),_hbin=3D_NA(),_pA=3D_NA();=0A=
_lv.id=3D_lv.pos=3D_lv.l=3D"";_hbE=3D_D("hbE")?_hbE:"";_hbEC=3D_D("hbEC")=
?_hbEC:0;var _ex=3D"expires=3DWed, 1 Jan 2020 00:00:00 =
GMT",_lvm=3D_D("lvm")?_lvm:150;=0A=
function _D(v){return(typeof =
eval("window._"+v)!=3D_hud)?eval("window._"+v):""}function =
_DD(v){return(typeof v!=3D_hud)?1:0}=0A=
function _A(v,c){return escape((_D("lc")=3D=3D"y"&&_DD(c))?_TL(v):v)}=0A=
function _B(){return 0}function _GP(){return =
location.protocol=3D=3D"https:"?"https://":"http://"}=0A=
function _IC(a,b,c){return a.charAt(b)=3D=3Dc?1:0}function =
_II(a,b,c){return a.indexOf(b,c?c:0)}function _IL(a){return =
a!=3D_hud?a.length:0}=0A=
function _IF(a,b,c){return a.lastIndexOf(b,c?c:_IL(a))}function =
_IP(a,b){return a.split(b)}=0A=
function _IS(a,b,c){return b>_IL(a)?"":a.substring(b,c!=3Dnull?c:_IL(a))}=0A=
function =
_RP(a,b,c,d){d=3D_II(a,b);if(d>-1){a=3D_RP(_IS(a,0,d)+","+_IS(a,d+_IL(b),=
_IL(a)),b,c)}return a}=0A=
function _TL(a){return a.toLowerCase()}function _TS(a){return =
a.toString()}function _TV(){_hbSend()}function _SV(a,b,c){_hbSet(a,b,c)}=0A=
function _CL(a){return _D(a)?_D(a):a=3D=3D"lidt"?"lid":"lpos"}function =
_VS(a,b){eval("_"+a+"=3D'"+b+"'")}=0A=
function =
_VC(a,b,c,d){b=3D_IP(a,",");for(c=3D0;c<_IL(b);c++){d=3D_IP(b[c],"|");_VS=
(d[0],(_D(d[0]))?_D(d[0]):d[1]?d[1]:"")}}=0A=
for(var =
_a=3D0;_a<_hbEC;_a++){_pv=3D_hbE[_a];if(_pv._N=3D=3D"pv"){for(var _b in =
_pv){if(_EE(_b)){_VS(_b,_pv[_b])}}}}=0A=
_VC("pn|PUT+PAGE+NAME+HERE,mlc|CONTENT+CATEGORY,elf|n,dlf|n,dft|n,pndef|t=
itle,ctdef|full,hcn|");=0A=
function =
_ER(a,b,c){_hbi.src=3D_GP()+_gn+"/HG?hc=3D"+_mn+"&hb=3D"+_A(_acct)+"&hec=3D=
1&vjs=3D"+_vjs+"&vpc=3DERR&ec=3D1&err=3D"=0A=
+((typeof a=3D=3D"string")?_A(a+"-"+c):"Unknown")}function =
_EE(a){return(a!=3D"_N"&&a!=3D"_C")?1:0}_EV(window,"error",_ER);=0A=
function _hbSend(c,a,i){a=3D"";_hec++;for(i in _hbA)if(typeof =
_hbA[i]!=3D"function")a+=3D"&"+i+"=3D"+_hbA[i];_Q(_hbq+"&hec=3D"+_hec+a+_=
hbSendEV());_hbA=3D_NA()}=0A=
function =
_hbSet(a,b,c,d,e){d=3D_II(_hbq,"&"+a+"=3D");if(d>-1){e=3D_II(_hbq,"&",d+1=
);e=3De>d?e:_IL(_hbq);if(a=3D=3D"n"||a=3D=3D"vcon"){_hbq=3D_IS(_hbq,0,d)+=
"&"+a+"=3D"+b+=0A=
_IS(_hbq,e);_hec=3D-1;if(a=3D=3D"n"){_pn=3Db}else{_mlc=3Db}}else{_hbq=3D_=
IS(_hbq,0,d)+_IS(_hbq,e)}}if((a!=3D"n")&&(a!=3D"vcon"))_hbA[a]=3D(c=3D=3D=
0)?b:_A(b)}=0A=
function =
_hbRedirect(a,b,c,d,e,f,g){_SV("n",a);_SV("vcon",b);if(_DD(d)&&_IL(d)>0){=
d=3D_IC(d,0,"&")?_IS(d,1,_IL(d)):d;e=3D_IP(d,"&");for(f=3D0;f<_IL(e);=0A=
f++){g=3D_IP(e[f],"=3D");_SV(g[0],g[1])}}_TV();if(c!=3D""){_SV("hec",0);s=
etTimeout("location.href=3D'"+c+"'",500)}}=0A=
function =
_hbSendEV(a,b,c,d,e,f,x,i){a=3Dc=3D"",e=3D_IL(_hbE);for(b=3D0;b<e;b++){c=3D=
_hbE[b];for(var d in c){if(_EE(d)&&c[d].match){x=3Dc[d].match(/\[\]/g);=0A=
if(x!=3Dnull&&_IL(x)>c._C)c._C=3D_IL(x)}}for(d in =
c){if(_EE(d)&&c[d].match){x=3Dc[d].match(/\[\]/g);x=3D(x=3D=3Dnull)?0:_IL=
(x);for(i=3Dx;i<c._C;i++)c[d]+=3D"[]"}}}=0A=
for(b=3D0;b<e;b++){c=3D_hbE[b];for(f=3Db+1;f<e;f++){if(_hbE[f]!=3Dnull&&c=
._N=3D=3D_hbE[f]._N){for(d in =
c){if(_EE(d)&&_hbE[f]!=3Dnull)c[d]+=3D"[]"+_hbE[f][d];=0A=
_hbE[f][d]=3D""}}}for(d in =
c){if(_EE(d)&&c._N!=3D""&&c._N!=3D"pv"){a+=3D"&"+c._N+"."+d+"=3D"+_RP(_A(=
c[d]),"%5B%5D",",")}}}_hbE=3D_NA();_hbEC=3D0;return a}=0A=
function =
_hbM(a,b,c,d){_SV('n',a);_SV('vcon',b);if(_IL(c)>0)_SV(c,d);_TV()}=0A=
function _hbPageView(p,m){_hec=3D-1;_hbM(p,m,"")}function =
_hbExitLink(n){_hbM(_pn,_mlc,"el",n)}function =
_hbDownload(n){_hbM(_pn,_mlc,"fn",n)}=0A=
function =
_hbVisitorSeg(n,p,m){_SV("n",p);_SV("vcon",m);_SV("seg",n,1);_TV()}functi=
on _hbCampaign(n,p,m){_hbM(p,m,"cmp",n)}=0A=
function _hbFunnel(n,p,m){_hbM(p,m,"fnl",n)}function =
_hbGoalPage(n,p,m){_hbM(p,m,"gp",n)}=0A=
function _hbLink(a,b,c){_SV("lid",a);if(_DD(b))_SV("lpos",b);_TV()}=0A=
function =
_LE(a,b,c,d,e,f,g,h,i,j,k,l){b=3D"([0-9A-Za-z\\-]*\\.)",c=3Dlocation.host=
name,d=3Da.href,h=3Di=3D"";eval("_f=3D/"+b+"*"+b+"/");if(_DD(_f)){_f.exec=
(c);	=0A=
j=3D(_DD(_elf))?_elf:"";if(j!=3D"n"){if(_II(j,"!")>-1){h=3D_IS(j,0,_II(j,=
"!"));i=3D_IS(j,_II(j,"!")+1,_IL(j))}else{h=3Dj}}k=3D0;if(_DD(_elf)&&_elf=
!=3D"n"){=0A=
if(_IL(i)){l=3D_IP(i,",");for(g=3D0;g<_IL(l);g++)if(_II(d,l[g])>-1)return=
}if(_IL(h)){l=3D_IP(h,",");for(g=3D0;g<_IL(h);g++)if(_II(d,l[g])>-1)k=3D1=
}}=0A=
if(_II(a.hostname,RegExp.$2)<0||k){	e=3D_IL(d)-1;return =
_IC(d,e,'/')?_IS(d,0,e):d}}}=0A=
function =
_LD(a,b,c,d,e,f){b=3Da.pathname,d=3De=3D"";b=3D_IS(b,_IF(b,"/")+1,_IL(b))=
;c=3D(_DD(_dlf))?_dlf:"";if(c!=3D"n"){if(_II(c,"!")>-1){d=3D","+_IS(c,0,_=
II(c,"!"));=0A=
e=3D","+_IS(c,_II(c,"!")+1,_IL(c))}else{d=3D","+c}}f=3D_II(b,"?");b=3D(f>=
-1)?_IS(b,0,f):b;if(_IF(b,".")>-1){f=3D_IS(b,_IF(b,"."),_IL(b));=0A=
if(_II(_dl+d,f)>-1&&_II(e,f)<0){var =
dl=3Db;if(_DD(_dft)){if(_dft=3D=3D"y"&&a.name){dl=3Da.name}else =
if(_dft=3D=3D"full"){dl=3Da.pathname}}return dl}}}=0A=
function =
_LP(a,b,c){for(c=3D0;c<_IL(a);c++){if(b=3D=3D0){if(_IL(_lv.l)<_lvm)_LV(a[=
c]);else break}else if(b=3D=3D1)_EV(a[c],'mousedown',_LT)}}=0A=
function =
_LV(a,b,c){b=3D_LN(a);c=3Db[0]+b[1];if(_IL(c)){_lv.id+=3D_A(b[0])+",";_lv=
.pos+=3D_A(b[1])+",";_lv.l+=3Dc}}=0A=
function =
_LN(a,b,c,d){b=3Da.href;b+=3Da.name?a.name:"";c=3D_LVP(b,_CL("lidt"));d=3D=
_LVP(b,_CL("lpost"));return[c,d]}=0A=
function =
_LT(e){if((e.which&&e.which=3D=3D1)||(e.button&&e.button=3D=3D1)){var =
a=3Ddocument.all?window.event.srcElement:this;for(var =
i=3D0;i<4;i++){if(a.tagName&&=0A=
_TL(a.tagName)!=3D"a"&&_TL(a.tagName)!=3D"area"){a=3Da.parentElement}}var=
 =
b=3D_LN(a),c=3Dd=3D"";a.lid=3Db[0];a.lpos=3Db[1];if(_D("lt")&&_lt!=3D"man=
ual"){if((a.tagName&&=0A=
_TL(a.tagName)=3D=3D"area")){if(!_IL(a.lid)){if(a.parentNode){if(a.parent=
Node.name)a.lid=3Da.parentNode.name;else =
a.lid=3Da.parentNode.id}}if(!_IL(a.lpos))=0A=
a.lpos=3Da.coords}else{if(_IL(a.lid)<1)a.lid=3D_LS(a.text?a.text:a.innerT=
ext?a.innerText:"");if(!_IL(a.lid)||_II(_TL(a.lid),"<img")>-1)a.lid=3D_LI=
(a)}}=0A=
if(!_IL(a.lpos)&&_D("lt")=3D=3D"auto_pos"&&a.tagName&&_TL(a.tagName)!=3D"=
area"){c=3Ddocument.links;for(d=3D0;d<_IL(c);d++){if(a=3D=3Dc[d]){a.lpos=3D=
d+1;break}}}=0A=
var _f=3D0,j=3Dk=3D"",l=3D(a.protocol)?_TL(a.protocol):"";=0A=
if(l&&l!=3D"mailto:"&&l!=3D"javascript:"){j=3D_LE(a),k=3D_LD(a);if(_DD(k)=
)a.fn=3Dk;else if(_DD(j))a.el=3Dj}=0A=
if(_D("lt")&&_IC(_lt,0,"n")!=3D1&&_DD(a.lid)&&_IL(a.lid)>0){_SV("lid",a.l=
id);if(_DD(a.lpos))_SV("lpos",a.lpos);_f=3D1}if(_DD(a.fn)){_SV("fn",a.fn)=
;_f=3D2}=0A=
else if(_DD(a.el)){_SV("el",a.el);_f=3D1}if(_f>0){_TV()}}}=0A=
function =
_LVP(a,b,c,d,e){c=3D_II(a,"&"+b+"=3D");c=3Dc<0?_II(a,"?"+b+"=3D"):c;if(c>=
-1){d=3D_II(a,'&',c+_IL(b)+2);e=3D_IS(a,c+_IL(b)+2,d>-1?d:_IL(a));=0A=
if(!_ec){if(!(_II(e,"//")=3D=3D0))return e}else return e}return ""}=0A=
function _LI(a){var =
b=3D""+a.innerHTML,bu=3D_TL(b),i=3D_II(bu,"<img");if(bu&&i>-1){eval("__f=3D=
/ src\s*=3D\s*['\"]?([^'\" ]+)['\"]?/i");__f.exec(b);=0A=
if(RegExp.$1)b=3DRegExp.$1}return b}=0A=
function _LSP(a,b,c,d){d=3D_IP(a,b);return d.join(c)}=0A=
function =
_LS(a,b,c,d,e,f,g){c=3D_D("lim")?_lim:100;b=3D(_IL(a)>c)?_A(_IS(a,0,c)):_=
A(a);b=3D_LSP(b,"%0A","%20");b=3D_LSP(b,"%0D","%20");b=3D_LSP(b,"%09","%2=
0");=0A=
c=3D_IP(b,"%20");d=3D_NA();e=3D0;for(f=3D0;f<_IL(c);f++){g=3D_RP(c[f],"%2=
0","");if(_IL(g)>0){d[e++]=3Dg}}b=3Dd.join("%20");return unescape(b)}=0A=
function =
_EM(a,b,c,d){a=3D_D("fv");b=3D_II(a,";"),c=3DparseInt(a);d=3D3;if(_TL(a)=3D=
=3D"n"){d=3D999;_fv=3D""}else =
if(b>-1){d=3D_IS(a,0,b);_fv=3D_IS(a,b+1,_IL(a))}=0A=
else if(c>0){d=3Dc;_fv=3D""}return d}=0A=
function _FF(e){var a=3D(_bnN)?this:_EVO(e);_hlf=3D(a.lf)?a.lf:""}=0A=
function =
_FU(e){if(_hfs=3D=3D0&&_IL(_hlf)>0&&_fa=3D=3D1){_hfs=3D1;if(_hfc){_SV("sf=
","1")}else =
if(_IL(_hlf)>0){_SV("lf",_hlf)}_TV();_hlf=3D"",_hfs=3D0,_hfc=3D0}}=0A=
function _FO(e){var =
a=3Dtrue;if(_DD(this.FS))eval("try{a=3Dthis.FS()}catch(e){}");if(a!=3Dfal=
se)_hfc=3D1;return a}=0A=
function _FA(a,b,c,d,e,f,g,h,i,ff,fv,s){b=3Da.forms;ff=3Dnew =
Object();f=3D_EM();for(c=3D0;c<_IL(b);c++){ff=3Db[c],d=3Ds=3D0,e=3Dff.ele=
ments,fv=3Deval(_D("fv"));if(_DD(fv)=0A=
&&_TL(_TS(fv))!=3D"n"&&fv!=3D""&&typeof fv=3D=3D"function"){_fv=3Dnew =
Function("if("+_fv+"()){_fvf=3D0;_hfc=3D1}");_EV(ff,"submit",_fv),_fvf=3D=
1,_fa=3D1}g=3Dff.name?ff.name=0A=
:"forms["+c+"]";for(h=3D0;h<_IL(e);h++){if(e[h].type&&"hiddenbuttonsubmit=
imagereset".indexOf(e[h].type)<0&&d++>=3Df)break}if(d>=3Df){_fa=3D1;for(h=
=3D0;h<_IL(e);=0A=
h++){i=3De[h];if(i.type&&"hiddenbuttonsubmitimagereset".indexOf(i.type)<0=
){i.lf=3Dg+".";i.lf+=3D(i.name&&i.name!=3D"")?i.name:"elements["+h+"]";=0A=
_EV(i,"focus",_FF)}}ff.FS=3Dnull;ff.FS=3Dff.onsubmit;if(_DD(ff.FS)&&ff.FS=
!=3Dnull){ff.onsubmit=3D_FO}else =
if(!(_bnN&&_bv<5)&&_hM&&!(_bnI&&!_I5)){if((!_bnI)||=0A=
(_II(navigator.userAgent,"Opera")>-1)){ff.onsubmit=3D_FO}else{_EV(ff,"sub=
mit",_FO);=0A=
eval("try{document.forms["+c+"].FS=3Ddocument.forms["+c+"].submit;documen=
t.forms["+c+"].submit=3D_FO;throw ''}catch(E){}")}}}}}=0A=
function _GR(a,b,c,d){if(!_D("hrf"))return =
a;if(_II(_hrf,"http",0)>-1)return =
_hrf;b=3Dwindow.location.search;b=3D_IL(b)>1?_IS(b,1,_IL(b)):"";=0A=
c=3D_II(b,_hrf+"=3D");if(c>-1){ =
d=3D_II(b,"&",c+1);d=3Dd>c?d:_IL(b);b=3D_IS(b,c+_IL(_hrf)+1,d)}return(b!=3D=
_hud&&_IL(b)>0)?b:a}=0A=
function =
_PO(a,b,c,d,e,f,g){d=3Dlocation,e=3Dd.pathname,f=3D_IS(e,_IF(e,"/")+1),g=3D=
document.title;if(a&&b=3D=3Dc){return(_pndef=3D=3D"title"&&g!=3D""&&g!=3D=
d&&=0A=
!(_bnN&&_II(g,"http")>0))?g:f?f:_pndef}else{return =
b=3D=3Dc?(e=3D=3D""||e=3D=3D"/")?"/":_IS(e,(_ctdef!=3D"full")?_IF(e,"/",_=
IF(e,"/")-2):_II(e,"/"),_IF(e,"/"))=0A=
:(b=3D=3D"/")?b:((_II(b,"/")?"/":"")+(_IF(b,"/")=3D=3D_IL(b)-1?_IS(b,0,_I=
L(b)-1):b))}}=0A=
function _PP(a,b,c,d){return =
""+(c>-1?_PO(b,_IS(a,0,c),d)+";"+_PP(_IS(a,c+1),b,_II(_IS(a,c+1),";")):_P=
O(b,a,d))}=0A=
_mlc=3D_PP(_mlc,0,_II( =
_mlc,";"),"CONTENT+CATEGORY");_pn=3D_PP(_pn,1,_II(_pn,";"),"PUT+PAGE+NAME=
+HERE");=0A=
function _NN(a){return =
_D(a)!=3D"none"}if(_NN("lt")){_LP(document.links,0)}=0A=
var =
_rf=3D_A(document.referrer),_et=3D_oe=3D_we=3D0,_ar=3D"",_hM=3D(!(_II(nav=
igator.userAgent,"Mac")>-1)),_tls=3D"";_bv=3DparseInt(navigator.appVersio=
n);=0A=
_bv=3D(_bv>99)?(_bv/100):_bv;var =
__f,_hrat=3D_D("hra"),_hra=3D"",_$r=3D"document.referrer)+''}",_$c=3D"cat=
ch(_e)",_hbi=3Dnew Image(),_fa=3D_hlfs=3D_hoc=3D0,=0A=
_hlf=3D_ce=3D_ln=3D_pl=3D'',_bn=3Dnavigator.appName,_bn=3D(_II(_bn,"Micro=
soft")?_bn:"MSIE"),_bnN=3D(_bn=3D=3D"Netscape"),_bnI=3D(_bn=3D=3D"MSIE"),=
_hck=3D"*; path=3D/; "+(_D("cpd")&&=0A=
_D("cpd")!=3D""?(" domain=3D."+_D("cpd")+"; =
"):"")+_ex,_N6=3D(_bnN&&_bv>4),_I5=3D((_II(navigator.userAgent,'MSIE =
5')>-1)||=0A=
(_II(navigator.userAgent,'MSIE =
6')>-1)),_ss=3D_sc=3D"na",_sv=3D11,_cy=3D_hp=3D"u",_tp=3D_D("ptc");if(_N6=
||_I5)eval("try{_tls=3Dtop.location.search}catch(_e){}")=0A=
function _E(a){var b=3D"";var d=3D_IP(a,",");for(var =
c=3D0;c<_IL(d);c++)b+=3D"&"+d[c]+"=3D"+_A(_D(d[c]));return b}=0A=
function =
_F(a,b){return(!_II(a,"?"+b+"=3D"))?0:_II(a,"&"+b+"=3D")}function =
_G(a,b,c,d){var =
e=3D_F(a,b);if(d&&e<0&&top&&window!=3Dtop){e=3D_F(_tls,b);=0A=
if(e>-1)a=3D_tls};return(e>-1)?_IS(a,e+2+_IL(b),(_II(a,"&",e+1)>-1)?_II(a=
,"&",e+1):_IL(a)):c}=0A=
function =
_H(a,b,c){if(!a)a=3Dc;if(_I5||_N6){eval("try{_vv=3D_G(location.search,'"+=
a+"','"+b+"',1)}"+_$c+"{}")}else{_vv=3D_G(location.search,a,b,1)}return =
unescape(_vv)}=0A=
function =
_I(a,b,c,d){__f=3D_IS(a,_II(a,"?"));if(b){if(_I5||_N6){eval("try{_hra=3D_=
G(__f,_hqsr,_hra,0)}"+_$c+"{}")}else{_hra=3D_G(__f,_hqsr,_hra,0)}};=0A=
if(c&&!_hra){if(_I5||_N6){eval("try{_hra=3D_G(location.search,_hqsp,_hra,=
1)}"+_$c+"{}")}else{_hra=3D_G(location.search,_hqsp,_hra,1)}};if(d&&!_hra=
)_hra=3Dd;return _hra}=0A=
_dcmpe=3D_H(_D("dcmpe"),_D("dcmpe"),"DCMPE");_dcmpre=3D_H(_D("dcmpre"),_D=
("dcmpre"),"DCMPRE");_vv=3D"";_cmp=3D_H(_D("cmpn"),_D("cmp"),"CMP");=0A=
_gp=3D_H(_D("gpn"),_D("gp"),"GP");_dcmp=3D_H(_D("dcmpn"),_D("dcmp"),"DCMP=
");=0A=
if(_II(_cmp,"SFS-")>-1){document.cookie=3D"HBCMP=3D"+_cmp+"; =
path=3D/;"+(_cpd!=3D""?(" domain=3D."+_cpd+"; "):"")+_ex}=0A=
function =
_J(a,b){return(_II(a,"CP=3D")<0)?"null":_IS(a,_II(a,"CP=3D")+3,(b=3D=3D"*=
")?_II(a,"*"):null)}=0A=
if(_bnI&&_bv>3)_ln=3Dnavigator.userLanguage;if(_bnN){if(_bv>3)_ln=3Dnavig=
ator.language;if(_bv>2)for(var i=3D0;i<_IL(navigator.plugins);i++)_pl+=3D=0A=
navigator.plugins[i].name+":"};var =
_cp=3D_D("cp");if(location.search&&_TL(_cp)=3D=3D"null")_cp=3D_J(location=
.search,"x");if(_II(document.cookie,"CP=3D")>-1){=0A=
_ce=3D"y";_hd=3D_J(document.cookie,"*");if(_TL(_hd)!=3D"null"&&_cp=3D=3D"=
null"){_cp=3D_hd}else{document.cookie=3D"CP=3D"+_cp+_hck}}else{document.c=
ookie=3D"CP=3D"+_cp+_hck;=0A=
_ce=3D(_II(document.cookie,"CP=3D")>-1)?"y":"n"};if(window.screen){_sv=3D=
12;_ss=3Dscreen.width+"*"+screen.height;_sc=3D_bnI?screen.colorDepth:scre=
en.pixelDepth;=0A=
if(_sc=3D=3D_hud)_sc=3D"na"};_ra=3D_NA();if(_ra.toSource||(_bnI&&_ra.shif=
t))_sv=3D13;if(_I5&&_hM){if(_II(""+navigator.appMinorVersion,"Privacy")>-=
1)_ce=3D"p";=0A=
if(document.body&&document.body.addBehavior){document.body.addBehavior("#=
default#homePage");_hp=3Ddocument.body.isHomePage(location.href)?"y":"n";=0A=
document.body.addBehavior("#default#clientCaps");_cy=3Ddocument.body.conn=
ectionType}};var =
_hcc=3D(_DD(_hcn))?_D("hcv"):"";if(!_D("gn"))_gn=3D"ehg.hitbox.com";=0A=
if(_D("ct")&&!_D("mlc"))_mlc=3D_ct;_ar=3D_GP()+_gn+"/HG?hc=3D"+_mn+"&hb=3D=
"+_A(_acct)+"&cd=3D1&hv=3D6&n=3D"+_A(_pn,1)+"&con=3D&vcon=3D"+_A(_mlc,1)+=
"&tt=3D"+_D("lt")+=0A=
"&ja=3D"+(navigator.javaEnabled()?"y":"n")+"&dt=3D"+(new =
Date()).getHours()+"&zo=3D"+(new =
Date()).getTimezoneOffset()+"&lm=3D"+Date.parse(document.lastModified)=0A=
+(_tp?("&pt=3D"+_tp):"")+_E((_bnN?"bn,":"")+"ce,ss,sc,sv,cy,hp,ln,vpc,vjs=
,hec,pec,cmp,gp,dcmp,dcmpe,dcmpre,cp,fnl")+"&seg=3D"+_D("seg")+"&epg=3D"+=
_D("epg")+=0A=
"&cv=3D"+_A(_hcc)+"&gn=3D"+_A(_D("hcn"))+"&ld=3D"+_A(_D("hlt"))+"&la=3D"+=
_A(_D("hla"))+"&c1=3D"+_A(_D("hc1"))+"&c2=3D"+_A(_D("hc2"))+"&c3=3D"+_A(_=
D("hc3"))+"&c4=3D"+=0A=
_A(_D("hc4"))+"&customerid=3D"+_A(_D("ci")?_ci:_D("cid"))+"&lv.id=3D"+_lv=
.id+"&lv.pos=3D"+_lv.pos;if(_I5||_N6){eval("try{_rf=3D_A(top."+_$r+_$c+"{=
_rf=3D_A("+_$r)}=0A=
else{if(top.document&&_IL(parent.frames)>1){_rf=3D_A(document.referrer)+"=
"}else =
if(top.document){_rf=3D_A(top.document.referrer)+""}}if((_rf=3D=3D_hud)||=0A=
(_rf=3D=3D""))_rf=3D"bookmark";_rf=3Dunescape(_rf);_rf=3D_GR(_rf);_hra=3D=
_I(_rf,_D("hqsr"),_D("hqsp"),_hrat);_ar+=3D"&ra=3D"+_A(_hra)+"&rf=3D"+_A(=
_IS(_rf,0,500))+=0A=
"&pl=3D"+_A(_pl)+_hbSendEV();if(_D("onlyMedia")!=3D"y"){var =
$t1=3D"",$t2=3D_CL("lidt"),$t3=3D_CL("lpost"),$t4=3D0;if($t2!=3D"lid"){$t=
4=3D1;$t1+=3D$t2}if($t3!=3D"lpos")=0A=
{$t4=3D1;$t1+=3D","+$t3}if($t4){_ar+=3D"&ttt=3D"+$t1}_hbi.src=3D_ar+"&hid=
=3D"+Math.random()}_hbq=3D_IS(_ar,0,_II(_ar,"&hec"));_hbE=3D_NA();=0A=
function _Q(a){var b=3D"";b=3Dnew =
Image();b.src=3Da+"&hid=3D"+Math.random()}=0A=
function =
_X(a){if(_ec=3D=3D0){_ec=3D1;a=3Ddocument;if(_NN("lt")||_NN("dlf")||_NN("=
elf")){_LP(a.links,1)}if(_NN("fv"))_FA(a)}}=0A=
function =
_EV(a,b,c){if(a.addEventListener){a.addEventListener(b,c,false)}else =
if(a.attachEvent){a.attachEvent("on"+b,c)}}=0A=
function _EVO(e){return document.all?window.event.srcElement:this} =0A=
_EV(window,"load",_X);_EV(window,(_bnI&&_DD(window.onbeforeunload))?"befo=
reunload":"unload",_FU);setTimeout("_X()",3000);=0A=

------=_NextPart_000_0000_01C8587B.C3B54E40--
